Azerotcore-wotlk
stdsoap2.cpp
Go to the documentation of this file.
1 /*
2  stdsoap2.c[pp] 2.8.105
3 
4  gSOAP runtime engine
5 
6 gSOAP XML Web services tools
7 Copyright (C) 2000-2020, Robert van Engelen, Genivia Inc., All Rights Reserved.
8 This part of the software is released under ONE of the following licenses:
9 GPL or the gSOAP public license.
10 --------------------------------------------------------------------------------
11 Contributors:
12 
13 Wind River Systems, Inc., for the following addition licensed under the gSOAP
14 public license:
15  - vxWorks compatible, enabled with compiler option -DVXWORKS
16 --------------------------------------------------------------------------------
17 gSOAP public license.
18 
19 The contents of this file are subject to the gSOAP Public License Version 1.3
20 (the "License"); you may not use this file except in compliance with the
21 License. You may obtain a copy of the License at
22 http://www.cs.fsu.edu/~engelen/soaplicense.html
23 Software distributed under the License is distributed on an "AS IS" basis,
24 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
25 for the specific language governing rights and limitations under the License.
26 
27 The Initial Developer of the Original Code is Robert A. van Engelen.
28 Copyright (C) 2000-2020, Robert van Engelen, Genivia Inc., All Rights Reserved.
29 --------------------------------------------------------------------------------
30 GPL license.
31 
32 This program is free software; you can redistribute it and/or modify it under
33 the terms of the GNU General Public License as published by the Free Software
34 Foundation; either version 2 of the License, or (at your option) any later
35 version.
36 
37 This program is distributed in the hope that it will be useful, but WITHOUT ANY
38 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
39 PARTICULAR PURPOSE. See the GNU General Public License for more details.
40 
41 You should have received a copy of the GNU General Public License along with
42 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
43 Place, Suite 330, Boston, MA 02111-1307 USA
44 
45 Author contact information:
46 engelen@genivia.com / engelen@acm.org
47 
48 This program is released under the GPL with the additional exemption that
49 compiling, linking, and/or using OpenSSL is allowed.
50 --------------------------------------------------------------------------------
51 A commercial use license is available from Genivia, Inc., contact@genivia.com
52 --------------------------------------------------------------------------------
53 */
54 
55 #define GSOAP_LIB_VERSION 208105
56 
57 #ifdef AS400
58 # pragma convert(819) /* EBCDIC to ASCII */
59 #endif
60 
61 #if defined(__gnu_linux__) && !defined(_GNU_SOURCE)
62 # define _GNU_SOURCE 1
63 #endif
64 
65 #include "stdsoap2.h"
66 
67 #if GSOAP_VERSION != GSOAP_LIB_VERSION
68 # error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE"
69 #endif
70 
71 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
72 # include <ipcom_key_db.h> /* vxWorks compatible */
73 #endif
74 
75 #ifdef __BORLANDC__
76 # pragma warn -8060
77 #else
78 # ifdef WIN32
79 # ifdef UNDER_CE
80 # pragma comment(lib, "ws2.lib") /* WinCE */
81 # else
82 # pragma comment(lib, "Ws2_32.lib")
83 # endif
84 # pragma warning(disable : 4996) /* disable deprecation warnings */
85 # endif
86 #endif
87 
88 #ifdef __cplusplus
89 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.105 2020-07-22 00:00:00 GMT")
90 extern "C" {
91 #else
92 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.105 2020-07-22 00:00:00 GMT")
93 #endif
94 
95 /* 8bit character representing unknown character entity or multibyte data */
96 #ifndef SOAP_UNKNOWN_CHAR
97 # define SOAP_UNKNOWN_CHAR (0x7F)
98 #endif
99 
100 /* unicode character representing unknown characters outside the XML 1.0 UTF8 unicode space */
101 #ifdef WITH_REPLACE_ILLEGAL_UTF8
102 # ifndef SOAP_UNKNOWN_UNICODE_CHAR
103 # define SOAP_UNKNOWN_UNICODE_CHAR (0xFFFD)
104 # endif
105 #endif
106 
107 /* EOF=-1 */
108 #define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */
109 #define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */
110 #define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */
111 #define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */
112 #define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */
113 
114 #define soap_coblank(c) ((c)+1 > 0 && (c) <= 32)
115 
116 #if defined(WIN32) && !defined(UNDER_CE)
117 #define soap_hash_ptr(p) ((size_t)((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)))
118 #else
119 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
120 #endif
121 
122 #ifdef SOAP_DEBUG
123 static void soap_init_logs(struct soap*);
124 static void soap_close_logfile(struct soap*, int);
125 static void soap_set_logfile(struct soap*, int, const char*);
126 #endif
127 
128 #ifdef SOAP_MEM_DEBUG
129 static void soap_init_mht(struct soap*);
130 static void soap_free_mht(struct soap*);
131 static void soap_track_unlink(struct soap*, const void*);
132 #endif
133 
134 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
135 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
136 static int soap_getattrval(struct soap*, char*, size_t*, soap_wchar);
137 static void soap_version(struct soap*);
138 static void soap_free_ns(struct soap*);
139 static soap_wchar soap_char(struct soap*);
140 static soap_wchar soap_getpi(struct soap*);
141 static int soap_isxdigit(int);
142 static void *fplugin(struct soap*, const char*);
143 static ULONG64 soap_count_attachments(struct soap*);
144 static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
145 static int soap_init_send(struct soap*);
146 
147 #ifdef WITH_NTLM
148 static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port);
149 #endif
150 
151 #ifndef WITH_NOIDREF
152 static int soap_has_copies(struct soap*, const char*, const char*);
153 static int soap_type_punned(struct soap*, const struct soap_ilist*);
154 static int soap_is_shaky(struct soap*, void*);
155 static void soap_init_iht(struct soap*);
156 static void soap_free_iht(struct soap*);
157 #endif
158 static void soap_init_pht(struct soap*);
159 static void soap_free_pht(struct soap*);
160 
161 #ifndef WITH_LEAN
162 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
163 static int soap_isnumeric(struct soap*, const char*);
164 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly);
165 static void soap_utilize_ns(struct soap *soap, const char *tag, short isearly);
166 static const wchar_t* soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern);
167 static wchar_t* soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu);
168 #endif
169 
170 static const char* soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern);
171 static char* soap_collapse(struct soap *soap, char *s, int flag, int insitu);
172 static const char* soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern);
173 
174 #ifndef WITH_LEANER
175 static int soap_begin_attachments(struct soap*);
176 static int soap_end_attachments(struct soap *soap);
177 static struct soap_multipart *soap_alloc_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, const char*, size_t);
178 static int soap_putdimefield(struct soap*, const char*, size_t);
179 static char *soap_getdimefield(struct soap*, size_t);
180 static void soap_select_mime_boundary(struct soap*);
181 static int soap_valid_mime_boundary(struct soap*);
182 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
183 #endif
184 
185 #ifdef WITH_GZIP
186 static int soap_getgziphdr(struct soap*);
187 #endif
188 
189 #ifdef WITH_OPENSSL
190 # ifndef SOAP_SSL_RSA_BITS
191 # define SOAP_SSL_RSA_BITS 2048
192 # endif
193 static int soap_ssl_init_done = 0;
194 static int ssl_auth_init(struct soap*);
195 static int ssl_verify_callback(int, X509_STORE_CTX*);
196 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
197 static int ssl_password(char*, int, int, void *);
198 #endif
199 
200 #ifdef WITH_GNUTLS
201 # ifndef SOAP_SSL_RSA_BITS
202 # define SOAP_SSL_RSA_BITS 2048
203 # endif
204 static int soap_ssl_init_done = 0;
205 static int ssl_auth_init(struct soap*);
206 static const char *ssl_verify(struct soap *soap, const char *host);
207 # if GNUTLS_VERSION_NUMBER < 0x020b00
208 # if defined(HAVE_PTHREAD_H)
209 # include <pthread.h>
210  /* make GNUTLS thread safe with pthreads */
211  GCRY_THREAD_OPTION_PTHREAD_IMPL;
212 # elif defined(HAVE_PTH_H)
213  #include <pth.h>
214  /* make GNUTLS thread safe with PTH */
215  GCRY_THREAD_OPTION_PTH_IMPL;
216 # endif
217 # endif
218 #endif
219 
220 #ifdef WITH_SYSTEMSSL
221 static int ssl_auth_init(struct soap*);
222 static int ssl_recv(int sk, void *s, int n, char *user);
223 static int ssl_send(int sk, void *s, int n, char *user);
224 #endif
225 
226 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
227 static const char * soap_decode(char*, size_t, const char*, const char*);
228 #endif
229 
230 #ifndef WITH_NOHTTP
231 static soap_wchar soap_getchunkchar(struct soap*);
232 static const char *http_error(struct soap*, int);
233 static int http_get(struct soap*);
234 static int http_put(struct soap*);
235 static int http_patch(struct soap*);
236 static int http_del(struct soap*);
237 static int http_200(struct soap*);
238 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, ULONG64);
239 static int http_send_header(struct soap*, const char*);
240 static int http_post_header(struct soap*, const char*, const char*);
241 static int http_response(struct soap*, int, ULONG64);
242 static int http_parse(struct soap*);
243 static int http_parse_header(struct soap*, const char*, const char*);
244 #endif
245 
246 #ifndef WITH_NOIO
247 
248 static int fsend(struct soap*, const char*, size_t);
249 static size_t frecv(struct soap*, char*, size_t);
250 static int tcp_init(struct soap*);
251 static const char *tcp_error(struct soap*);
252 
253 #if !defined(WITH_IPV6)
254 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
255 #endif
256 #if !defined(WITH_IPV6) || defined(WITH_COOKIES)
257 static int tcp_gethostbyname(struct soap*, const char *addr, struct hostent *hostent, struct in_addr *inaddr);
258 #endif
259 
260 static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
261 static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
262 static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
263 static int tcp_disconnect(struct soap*);
264 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
265 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
266 static const char *soap_strerror(struct soap*);
267 
268 #define SOAP_TCP_SELECT_RCV 0x1
269 #define SOAP_TCP_SELECT_SND 0x2
270 #define SOAP_TCP_SELECT_ERR 0x4
271 #define SOAP_TCP_SELECT_ALL 0x7
272 #define SOAP_TCP_SELECT_PIP 0x8
273 
274 #if defined(WIN32)
275  #define SOAP_SOCKBLOCK(fd) \
276  { \
277  u_long blocking = 0; \
278  ioctlsocket(fd, FIONBIO, &blocking); \
279  }
280  #define SOAP_SOCKNONBLOCK(fd) \
281  { \
282  u_long nonblocking = 1; \
283  ioctlsocket(fd, FIONBIO, &nonblocking); \
284  }
285 #elif defined(VXWORKS)
286  #define SOAP_SOCKBLOCK(fd) \
287  { \
288  u_long blocking = 0; \
289  ioctl(fd, FIONBIO, (int)(&blocking)); \
290  }
291  #define SOAP_SOCKNONBLOCK(fd) \
292  { \
293  u_long nonblocking = 1; \
294  ioctl(fd, FIONBIO, (int)(&nonblocking)); \
295  }
296 #elif defined(__VMS)
297  #define SOAP_SOCKBLOCK(fd) \
298  { \
299  int blocking = 0; \
300  ioctl(fd, FIONBIO, &blocking); \
301  }
302  #define SOAP_SOCKNONBLOCK(fd) \
303  { \
304  int nonblocking = 1; \
305  ioctl(fd, FIONBIO, &nonblocking); \
306  }
307 #elif defined(SYMBIAN)
308  #define SOAP_SOCKBLOCK(fd) \
309  { \
310  long blocking = 0; \
311  ioctl(fd, 0/*FIONBIO*/, &blocking); \
312  }
313  #define SOAP_SOCKNONBLOCK(fd) \
314  { \
315  long nonblocking = 1; \
316  ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
317  }
318 #else
319  #define SOAP_SOCKBLOCK(fd) (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
320  #define SOAP_SOCKNONBLOCK(fd) (void)fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
321 #endif
322 
323 #endif
324 
325 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
326 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
327 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
328 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
329 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
330 
331 const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}};
332 const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
333 const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
334 
335 #ifndef WITH_LEAN
336 static const char soap_indent[21] = "\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
337 /* Alternative indentation form for SOAP_XML_INDENT with spaces instead of tabs:
338 static const char soap_indent[41] = "\n ";
339 */
340 #endif
341 
342 #ifndef SOAP_CANARY
343 # define SOAP_CANARY (0xC0DE)
344 #endif
345 
346 static const char soap_padding[4] = "\0\0\0";
347 #define SOAP_STR_PADDING (soap_padding)
348 #define SOAP_STR_EOS (soap_padding)
349 #define SOAP_NON_NULL (soap_padding)
350 
351 #ifndef WITH_LEAN
352 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
353 {
354  { 160, "nbsp" },
355  { 161, "iexcl" },
356  { 162, "cent" },
357  { 163, "pound" },
358  { 164, "curren" },
359  { 165, "yen" },
360  { 166, "brvbar" },
361  { 167, "sect" },
362  { 168, "uml" },
363  { 169, "copy" },
364  { 170, "ordf" },
365  { 171, "laquo" },
366  { 172, "not" },
367  { 173, "shy" },
368  { 174, "reg" },
369  { 175, "macr" },
370  { 176, "deg" },
371  { 177, "plusmn" },
372  { 178, "sup2" },
373  { 179, "sup3" },
374  { 180, "acute" },
375  { 181, "micro" },
376  { 182, "para" },
377  { 183, "middot" },
378  { 184, "cedil" },
379  { 185, "sup1" },
380  { 186, "ordm" },
381  { 187, "raquo" },
382  { 188, "frac14" },
383  { 189, "frac12" },
384  { 190, "frac34" },
385  { 191, "iquest" },
386  { 192, "Agrave" },
387  { 193, "Aacute" },
388  { 194, "Acirc" },
389  { 195, "Atilde" },
390  { 196, "Auml" },
391  { 197, "Aring" },
392  { 198, "AElig" },
393  { 199, "Ccedil" },
394  { 200, "Egrave" },
395  { 201, "Eacute" },
396  { 202, "Ecirc" },
397  { 203, "Euml" },
398  { 204, "Igrave" },
399  { 205, "Iacute" },
400  { 206, "Icirc" },
401  { 207, "Iuml" },
402  { 208, "ETH" },
403  { 209, "Ntilde" },
404  { 210, "Ograve" },
405  { 211, "Oacute" },
406  { 212, "Ocirc" },
407  { 213, "Otilde" },
408  { 214, "Ouml" },
409  { 215, "times" },
410  { 216, "Oslash" },
411  { 217, "Ugrave" },
412  { 218, "Uacute" },
413  { 219, "Ucirc" },
414  { 220, "Uuml" },
415  { 221, "Yacute" },
416  { 222, "THORN" },
417  { 223, "szlig" },
418  { 224, "agrave" },
419  { 225, "aacute" },
420  { 226, "acirc" },
421  { 227, "atilde" },
422  { 228, "auml" },
423  { 229, "aring" },
424  { 230, "aelig" },
425  { 231, "ccedil" },
426  { 232, "egrave" },
427  { 233, "eacute" },
428  { 234, "ecirc" },
429  { 235, "euml" },
430  { 236, "igrave" },
431  { 237, "iacute" },
432  { 238, "icirc" },
433  { 239, "iuml" },
434  { 240, "eth" },
435  { 241, "ntilde" },
436  { 242, "ograve" },
437  { 243, "oacute" },
438  { 244, "ocirc" },
439  { 245, "otilde" },
440  { 246, "ouml" },
441  { 247, "divide" },
442  { 248, "oslash" },
443  { 249, "ugrave" },
444  { 250, "uacute" },
445  { 251, "ucirc" },
446  { 252, "uuml" },
447  { 253, "yacute" },
448  { 254, "thorn" },
449  { 255, "yuml" },
450  { 0, NULL }
451 };
452 #endif
453 
454 #ifndef WITH_NOIO
455 #ifndef WITH_LEAN
456 static const struct soap_code_map h_error_codes[] =
457 {
458 #ifdef HOST_NOT_FOUND
459  { HOST_NOT_FOUND, "Host not found" },
460 #endif
461 #ifdef TRY_AGAIN
462  { TRY_AGAIN, "Try Again" },
463 #endif
464 #ifdef NO_RECOVERY
465  { NO_RECOVERY, "No Recovery" },
466 #endif
467 #ifdef NO_DATA
468  { NO_DATA, "No Data" },
469 #endif
470 #ifdef NO_ADDRESS
471  { NO_ADDRESS, "No Address" },
472 #endif
473  { 0, NULL }
474 };
475 #endif
476 #endif
477 
478 #ifndef WITH_NOHTTP
479 #ifndef WITH_LEAN
480 static const struct soap_code_map h_http_error_codes[] =
481 {
482  { 100, "Continue" },
483  { 101, "Switching Protocols" },
484  { 200, "OK" },
485  { 201, "Created" },
486  { 202, "Accepted" },
487  { 203, "Non-Authoritative Information" },
488  { 204, "No Content" },
489  { 205, "Reset Content" },
490  { 206, "Partial Content" },
491  { 300, "Multiple Choices" },
492  { 301, "Moved Permanently" },
493  { 302, "Found" },
494  { 303, "See Other" },
495  { 304, "Not Modified" },
496  { 305, "Use Proxy" },
497  { 307, "Temporary Redirect" },
498  { 400, "Bad Request" },
499  { 401, "Unauthorized" },
500  { 402, "Payment Required" },
501  { 403, "Forbidden" },
502  { 404, "Not Found" },
503  { 405, "Method Not Allowed" },
504  { 406, "Not Acceptable" },
505  { 407, "Proxy Authentication Required" },
506  { 408, "Request Time-out" },
507  { 409, "Conflict" },
508  { 410, "Gone" },
509  { 411, "Length Required" },
510  { 412, "Precondition Failed" },
511  { 413, "Request Entity Too Large" },
512  { 414, "Request-URI Too Large" },
513  { 415, "Unsupported Media Type" },
514  { 416, "Requested range not satisfiable" },
515  { 417, "Expectation Failed" },
516  { 422, "Unprocessable Entity" },
517  { 426, "Upgrade Required" },
518  { 428, "Precondition Required" },
519  { 429, "Too Many Requests" },
520  { 431, "Request Header Fields Too Large" },
521  { 500, "Internal Server Error" },
522  { 501, "Not Implemented" },
523  { 502, "Bad Gateway" },
524  { 503, "Service Unavailable" },
525  { 504, "Gateway Time-out" },
526  { 505, "HTTP Version not supported" },
527  { 511, "Network Authentication Required" },
528  { 0, NULL }
529 };
530 #endif
531 #endif
532 
533 #ifdef WITH_OPENSSL
534 static const struct soap_code_map h_ssl_error_codes[] =
535 {
536 #define _SSL_ERROR(e) { e, #e }
537  _SSL_ERROR(SSL_ERROR_SSL),
538  _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
539  _SSL_ERROR(SSL_ERROR_WANT_READ),
540  _SSL_ERROR(SSL_ERROR_WANT_WRITE),
541  _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
542  _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
543  _SSL_ERROR(SSL_ERROR_SYSCALL),
544  { 0, NULL }
545 };
546 #endif
547 
548 #ifndef WITH_LEANER
549 static const struct soap_code_map mime_codes[] =
550 {
551  { SOAP_MIME_7BIT, "7bit" },
552  { SOAP_MIME_8BIT, "8bit" },
553  { SOAP_MIME_BINARY, "binary" },
554  { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
555  { SOAP_MIME_BASE64, "base64" },
556  { SOAP_MIME_IETF_TOKEN, "ietf-token" },
557  { SOAP_MIME_X_TOKEN, "x-token" },
558  { 0, NULL }
559 };
560 #endif
561 
562 #ifdef WIN32
563 static int tcp_done = 0;
564 #endif
565 
566 #if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
567 #ifndef h_errno
568 extern int h_errno;
569 #endif
570 #endif
571 
572 /******************************************************************************/
573 
574 #ifndef WITH_NOIO
575 static int
576 fsend(struct soap *soap, const char *s, size_t n)
577 {
578  int nwritten, err;
579  SOAP_SOCKET sk;
580  soap->errnum = 0;
581 #if defined(__cplusplus) && !defined(WITH_COMPAT)
582  if (soap->os)
583  {
584  soap->os->write(s, (std::streamsize)n);
585  if (soap->os->good())
586  return SOAP_OK;
587  return SOAP_EOF;
588  }
589 #endif
590  sk = soap->sendsk;
591  if (!soap_valid_socket(sk))
592  sk = soap->socket;
593  while (n)
594  {
595  if (soap_valid_socket(sk))
596  {
597  if (soap->send_timeout)
598  {
599  for (;;)
600  {
601  int r;
602 #ifdef WITH_SELF_PIPE
603 #ifdef WITH_OPENSSL
604  if (soap->ssl)
606  else
607 #endif
608 #ifdef WITH_GNUTLS
609  if (soap->session)
611  else
612 #endif
613 #ifdef WITH_SYSTEMSSL
614  if (soap->ssl)
616  else
617 #endif
619  if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */
620  {
621  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
622  return SOAP_EOF;
623  }
624 #else
625 #ifdef WITH_OPENSSL
626  if (soap->ssl)
628  else
629 #endif
630 #ifdef WITH_GNUTLS
631  if (soap->session)
633  else
634 #endif
635 #ifdef WITH_SYSTEMSSL
636  if (soap->ssl)
638  else
639 #endif
641 #endif
642  if (r > 0)
643  break;
644  if (!r)
645  return SOAP_EOF;
646  err = soap->errnum;
647  if (!err)
648  return soap->error;
649  if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
650  return SOAP_EOF;
651  }
652  }
653 #ifndef WITH_LEAN
654  if (soap->transfer_timeout)
655  {
656  time_t now = time(NULL);
657  if ((soap->transfer_timeout > 0 && difftime(now, (time_t)soap->start) > (double)soap->transfer_timeout)
658  || (soap->transfer_timeout < 0 && difftime(now, (time_t)soap->start) > -1000000.0 * (double)soap->transfer_timeout))
659  return SOAP_EOF;
660  }
661 #endif
662 #ifdef WITH_OPENSSL
663  if (soap->ssl)
664  nwritten = SSL_write(soap->ssl, s, (int)n);
665  else if (soap->bio)
666  nwritten = BIO_write(soap->bio, s, (int)n);
667  else
668 #endif
669 #ifdef WITH_GNUTLS
670  if (soap->session)
671  nwritten = gnutls_record_send(soap->session, s, n);
672  else
673 #endif
674 #ifdef WITH_SYSTEMSSL
675  if (soap->ssl)
676  {
677  err = gsk_secure_socket_write(soap->ssl, (char*)s, n, &nwritten);
678  if (err != GSK_OK)
679  nwritten = 0;
680  }
681  else
682 #endif
683 #ifndef WITH_LEAN
684  if ((soap->omode & SOAP_IO_UDP))
685  {
686  if (soap->peerlen)
687  nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, (SOAP_WINSOCKINT)soap->peerlen);
688  else
689  nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
690  /* retry and back-off algorithm */
691  /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
692  if (nwritten < 0)
693  {
694  int udp_repeat;
695  int udp_delay;
696  if ((soap->connect_flags & SO_BROADCAST))
697  udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
698  else
699  udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
700  udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
701  do
702  {
703  tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
704  if (soap->peerlen)
705  nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, (SOAP_WINSOCKINT)soap->peerlen);
706  else
707  nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
708  udp_delay <<= 1;
709  if (udp_delay > 500) /* UDP_UPPER_DELAY */
710  udp_delay = 500;
711  } while (nwritten < 0 && --udp_repeat > 0);
712  }
713  if (nwritten < 0)
714  {
715  err = soap_socket_errno;
716  if (err && err != SOAP_EINTR)
717  {
718  soap->errnum = err;
719  return SOAP_EOF;
720  }
721  nwritten = 0; /* and call write() again */
722  }
723  }
724  else
725 #endif
726 #if !defined(AS400)
727  nwritten = send(sk, s, (int)n, soap->socket_flags);
728 #else
729  nwritten = send(sk, (void*)s, n, soap->socket_flags);
730 #endif
731  if (nwritten <= 0)
732  {
733  int r = 0;
734  err = soap_socket_errno;
735 #ifdef WITH_OPENSSL
736  if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
737  {
738  soap->errnum = err;
739  return SOAP_EOF;
740  }
741 #endif
742 #ifdef WITH_GNUTLS
743  if (soap->session)
744  {
745  if (nwritten == GNUTLS_E_INTERRUPTED)
746  err = SOAP_EINTR;
747  else if (nwritten == GNUTLS_E_AGAIN)
748  err = SOAP_EAGAIN;
749  }
750 #endif
751  if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
752  {
753 #if defined(WITH_OPENSSL)
754  if (soap->ssl && r == SSL_ERROR_WANT_READ)
756  else
757 #elif defined(WITH_GNUTLS)
758  if (soap->session && !gnutls_record_get_direction(soap->session))
760  else
761 #endif
763  if (!r && soap->send_timeout)
764  return SOAP_EOF;
765  if (r < 0)
766  return SOAP_EOF;
767  }
768  else if (err && err != SOAP_EINTR)
769  {
770  soap->errnum = err;
771  return SOAP_EOF;
772  }
773  nwritten = 0; /* and call write() again */
774  }
775  }
776  else
777  {
778 #ifdef WITH_FASTCGI
779  nwritten = fwrite((void*)s, 1, n, stdout);
780  fflush(stdout);
781 #else
782 #ifdef UNDER_CE
783  nwritten = fwrite(s, 1, n, soap->sendfd);
784 #else
785 #ifdef WMW_RPM_IO
786  /* vxWorks compatible */
787  if (soap->rpmreqid)
788  nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
789  else
790 #endif
791 #ifdef WIN32
792  nwritten = _write(soap->sendfd, s, (unsigned int)n);
793 #else
794  nwritten = write(soap->sendfd, s, (unsigned int)n);
795 #endif
796 #endif
797 #endif
798  if (nwritten <= 0)
799  {
800 #ifndef WITH_FASTCGI
801  err = soap_errno;
802 #else
803  err = EOF;
804 #endif
805  if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
806  {
807  soap->errnum = err;
808  return SOAP_EOF;
809  }
810  nwritten = 0; /* and call write() again */
811  }
812  }
813  n -= nwritten;
814  s += nwritten;
815  }
816  return SOAP_OK;
817 }
818 #endif
819 
820 /******************************************************************************/
821 
823 int
825 soap_send_raw(struct soap *soap, const char *s, size_t n)
826 {
827  if (!s || !n)
828  return SOAP_OK;
829 #ifndef WITH_LEANER
831  return soap->error;
832  if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)) != SOAP_OK)
833  return soap->error;
834 #endif
835  if ((soap->mode & SOAP_IO_LENGTH))
836  {
837  soap->count += n;
838  }
839  else if ((soap->mode & SOAP_IO))
840  {
841  size_t i = sizeof(soap->buf) - soap->bufidx;
842  while (n >= i)
843  {
844  (void)soap_memcpy((void*)(soap->buf + soap->bufidx), i, (const void*)s, i);
845  soap->bufidx = sizeof(soap->buf);
846  if (soap_flush(soap))
847  return soap->error;
848  s += i;
849  n -= i;
850  i = sizeof(soap->buf);
851  }
852  (void)soap_memcpy((void*)(soap->buf + soap->bufidx), sizeof(soap->buf) - soap->bufidx, (const void*)s, n);
853  soap->bufidx += n;
854  }
855  else
856  {
857  return soap_flush_raw(soap, s, n);
858  }
859  return SOAP_OK;
860 }
861 
862 /******************************************************************************/
863 
865 int
868 {
869  size_t n = soap->bufidx;
870  if (!n)
871  return soap->error = soap->fsend(soap, SOAP_STR_EOS, 0); /* force a zero send for HTTP GET and DELETE */
872 #ifndef WITH_LEANER
873  if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
874  {
875  int r;
876  if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)) != SOAP_OK)
877  return soap->error = r;
878  }
879 #endif
880  soap->bufidx = 0;
881 #ifdef WITH_ZLIB
882  if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
883  {
884  soap->d_stream->next_in = (Byte*)soap->buf;
885  soap->d_stream->avail_in = (unsigned int)n;
886 #ifdef WITH_GZIP
887  soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
888 #endif
889  do
890  {
891  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
892  if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
893  {
894  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
895  return soap->error = SOAP_ZLIB_ERROR;
896  }
897  if (!soap->d_stream->avail_out)
898  {
899  if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf)))
900  return soap->error;
901  soap->d_stream->next_out = (Byte*)soap->z_buf;
902  soap->d_stream->avail_out = sizeof(soap->buf);
903  }
904  } while (soap->d_stream->avail_in);
905  return SOAP_OK;
906  }
907 #endif
908  return soap_flush_raw(soap, soap->buf, n);
909 }
910 
911 /******************************************************************************/
912 
914 int
916 soap_flush_raw(struct soap *soap, const char *s, size_t n)
917 {
918  if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
919  {
920  void *t;
921  t = soap_push_block(soap, NULL, n);
922  if (!t)
923  return soap->error = SOAP_EOM;
924  (void)soap_memcpy(t, n, (const void*)s, n);
925  return SOAP_OK;
926  }
927 #ifndef WITH_LEANER
928  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
929  {
930  char t[24];
931  (SOAP_SNPRINTF(t, sizeof(t), 20), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
932  DBGMSG(SENT, t, strlen(t));
933  soap->error = soap->fsend(soap, t, strlen(t));
934  if (soap->error)
935  return soap->error;
936  soap->chunksize += n;
937  }
938  DBGMSG(SENT, s, n);
939  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, (int)soap->socket, soap->sendfd));
940 #endif
941  return soap->error = soap->fsend(soap, s, n);
942 }
943 
944 /******************************************************************************/
945 
947 int
949 soap_send(struct soap *soap, const char *s)
950 {
951  if (!s)
952  return SOAP_OK;
953  return soap_send_raw(soap, s, strlen(s));
954 }
955 
956 /******************************************************************************/
957 
958 #ifndef WITH_LEANER
960 int
962 soap_send2(struct soap *soap, const char *s1, const char *s2)
963 {
964  if (soap_send(soap, s1))
965  return soap->error;
966  return soap_send(soap, s2);
967 }
968 #endif
969 
970 /******************************************************************************/
971 
972 #ifndef WITH_LEANER
974 int
976 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
977 {
978  if (soap_send(soap, s1)
979  || soap_send(soap, s2))
980  return soap->error;
981  return soap_send(soap, s3);
982 }
983 #endif
984 
985 /******************************************************************************/
986 
987 #ifndef WITH_LEANER
989 int
991 soap_query_send_key(struct soap *soap, const char *s)
992 {
993  if (!s)
994  return SOAP_OK;
995  if (!soap->body && soap_send_raw(soap, "&", 1))
996  return soap->error;
997  soap->body = 0;
998  (void)soap_encode_url(s, soap->msgbuf, (int)sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
999  return soap_send(soap, soap->msgbuf);
1000 }
1001 #endif
1002 
1003 /******************************************************************************/
1004 
1005 #ifndef WITH_LEANER
1006 SOAP_FMAC1
1007 int
1008 SOAP_FMAC2
1009 soap_query_send_val(struct soap *soap, const char *s)
1010 {
1011  if (!s)
1012  return SOAP_OK;
1013  if (soap_send_raw(soap, "=", 1))
1014  return soap->error;
1015  (void)soap_encode_url(s, soap->msgbuf, (int)sizeof(soap->msgbuf)); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
1016  return soap_send(soap, soap->msgbuf);
1017 }
1018 #endif
1019 
1020 /******************************************************************************/
1021 
1022 #ifndef WITH_LEANER
1023 SOAP_FMAC1
1024 char *
1025 SOAP_FMAC2
1027 {
1028  return strchr(soap->path, '?');
1029 }
1030 #endif
1031 
1032 /******************************************************************************/
1033 
1034 #ifndef WITH_LEANER
1035 SOAP_FMAC1
1036 char *
1037 SOAP_FMAC2
1038 soap_query_key(struct soap *soap, char **s)
1039 {
1040  char *t = *s;
1041  (void)soap;
1042  if (t && *t)
1043  {
1044  *s = (char*)soap_query_decode(t, strlen(t), t + 1);
1045  return t;
1046  }
1047  return *s = NULL;
1048 }
1049 #endif
1050 
1051 /******************************************************************************/
1052 
1053 #ifndef WITH_LEANER
1054 SOAP_FMAC1
1055 char *
1056 SOAP_FMAC2
1057 soap_query_val(struct soap *soap, char **s)
1058 {
1059  char *t = *s;
1060  (void)soap;
1061  if (t && *t == '=')
1062  {
1063  *s = (char*)soap_query_decode(t, strlen(t), t + 1);
1064  return t;
1065  }
1066  return NULL;
1067 }
1068 #endif
1069 
1070 /******************************************************************************/
1071 
1072 #ifndef WITH_LEANER
1073 SOAP_FMAC1
1074 const char *
1075 SOAP_FMAC2
1076 soap_query_decode(char *buf, size_t len, const char *val)
1077 {
1078  const char *s;
1079  char *t;
1080  for (s = val; *s; s++)
1081  if (*s != ' ' && *s != '=')
1082  break;
1083  if (*s == '"')
1084  {
1085  t = buf;
1086  s++;
1087  while (*s && *s != '"' && --len)
1088  *t++ = *s++;
1089  *t = '\0';
1090  do s++;
1091  while (*s && *s != '&' && *s != '=');
1092  }
1093  else
1094  {
1095  t = buf;
1096  while (*s && *s != '&' && *s != '=' && --len)
1097  {
1098  switch (*s)
1099  {
1100  case '+':
1101  *t++ = ' ';
1102  s++;
1103  break;
1104  case '\t':
1105  case '\n':
1106  case '\r':
1107  case ' ':
1108  s++;
1109  break;
1110  case '%':
1111  *t++ = ((s[1] >= 'A' ? (s[1]&0x7) + 9 : s[1] - '0') << 4) + (s[2] >= 'A' ? (s[2]&0x7) + 9 : s[2] - '0');
1112  s += 3;
1113  break;
1114  default:
1115  *t++ = *s++;
1116  }
1117  }
1118  *t = '\0';
1119  }
1120  return s;
1121 }
1122 #endif
1123 
1124 /******************************************************************************/
1125 
1126 #ifndef WITH_NOIO
1127 static size_t
1128 frecv(struct soap *soap, char *s, size_t n)
1129 {
1130  int r;
1131  int retries = 100; /* max 100 retries with non-blocking sockets */
1132  SOAP_SOCKET sk;
1133  soap->errnum = 0;
1134 #if defined(__cplusplus) && !defined(WITH_COMPAT)
1135  if (soap->is) /* recv from C++ stream */
1136  {
1137  if (soap->is->good())
1138  return (size_t)soap->is->read(s, (std::streamsize)n).gcount(); /* downcast to std::streamsize is OK: gcount() returns how much we got in s[] */
1139  return 0;
1140  }
1141 #else
1142  if (soap->is) /* recv from C buffer until NUL */
1143  {
1144  size_t l = strlen(soap->is);
1145  if (l > n)
1146  l = n;
1147  (void)soap_memcpy((void*)s, n, soap->is, l);
1148  soap->is += l;
1149  return l;
1150  }
1151 #endif
1152  sk = soap->recvsk;
1153  if (!soap_valid_socket(sk))
1154  sk = soap->socket;
1155  if (soap_valid_socket(sk))
1156  {
1157  for (;;)
1158  {
1159 #if defined(WITH_OPENSSL) || defined(WITH_SYSTEMSSL)
1160  int err = 0;
1161 #endif
1162 #ifdef WITH_OPENSSL
1163  if (soap->recv_timeout && !soap->ssl) /* OpenSSL: sockets are nonblocking so go ahead to read */
1164 #else
1165  if (soap->recv_timeout)
1166 #endif
1167  {
1168  for (;;)
1169  {
1170 #ifdef WITH_SELF_PIPE
1172  if ((r & SOAP_TCP_SELECT_PIP)) /* abort if data is pending on pipe */
1173  {
1174  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
1175  return 0;
1176  }
1177 #else
1179 #endif
1180  if (r > 0)
1181  break;
1182  if (!r)
1183  return 0;
1184  r = soap->errnum;
1185  if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
1186  return 0;
1187  }
1188  }
1189 #ifndef WITH_LEAN
1190  if (soap->transfer_timeout)
1191  {
1192  time_t now = time(NULL);
1193  if ((soap->transfer_timeout > 0 && difftime(now, (time_t)soap->start) > (double)soap->transfer_timeout)
1194  || (soap->transfer_timeout < 0 && difftime(now, (time_t)soap->start) > -1000000.0 * (double)soap->transfer_timeout))
1195  return 0;
1196  }
1197 #endif
1198 #ifdef WITH_OPENSSL
1199  if (soap->ssl)
1200  {
1201  r = SSL_read(soap->ssl, s, (int)n);
1202  if (r > 0)
1203  return (size_t)r;
1204  err = SSL_get_error(soap->ssl, r);
1205  if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
1206  return 0;
1207  }
1208  else if (soap->bio)
1209  {
1210  r = BIO_read(soap->bio, s, (int)n);
1211  if (r > 0)
1212  return (size_t)r;
1213  return 0;
1214  }
1215  else
1216 #endif
1217 #ifdef WITH_GNUTLS
1218  if (soap->session)
1219  {
1220  r = (int)gnutls_record_recv(soap->session, s, n);
1221  if (r >= 0)
1222  return (size_t)r;
1223  }
1224  else
1225 #endif
1226 #ifdef WITH_SYSTEMSSL
1227  if (soap->ssl)
1228  {
1229  err = gsk_secure_socket_read(soap->ssl, s, n, &r);
1230  if (err == GSK_OK && r > 0)
1231  return (size_t)r;
1232  if (err != GSK_OK && err != GSK_WOULD_BLOCK && err != GSK_WOULD_BLOCK_WRITE)
1233  return 0;
1234  }
1235  else
1236 #endif
1237  {
1238 #ifndef WITH_LEAN
1239  if ((soap->omode & SOAP_IO_UDP))
1240  {
1241  SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
1242  memset((void*)&soap->peer, 0, sizeof(soap->peer));
1243  r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, &soap->peer.addr, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h, SOAP_WINSOCKINT cast is safe due to limited range of n in the engine (64K) */
1244  soap->peerlen = (size_t)k;
1245 #ifdef WITH_IPV6
1246  soap->ip = 0;
1247  soap->ip6[0] = 0;
1248  soap->ip6[1] = 0;
1249  soap->ip6[2] = 0;
1250  soap->ip6[3] = 0;
1251 #else
1252  soap->ip = ntohl(soap->peer.in.sin_addr.s_addr);
1253  soap->ip6[0] = 0;
1254  soap->ip6[1] = 0;
1255  soap->ip6[2] = 0xFFFF;
1256  soap->ip6[3] = soap->ip;
1257 #endif
1258  }
1259  else
1260 #endif
1261  r = recv(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags); /* SOAP_WINSOCKINT cast is safe due to limited range of n in the engine (64K) */
1262  if (r >= 0)
1263  return (size_t)r;
1264  r = soap_socket_errno;
1265  if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
1266  {
1267  soap->errnum = r;
1268  return 0;
1269  }
1270  }
1271 #if defined(WITH_OPENSSL)
1272  if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
1274  else
1275 #elif defined(WITH_GNUTLS)
1276  if (soap->session && gnutls_record_get_direction(soap->session))
1278  else
1279 #elif defined(WITH_SYSTEMSSL)
1280  if (soap->ssl && err == GSK_WOULD_BLOCK_WRITE)
1282  else
1283 #endif
1285  if (!r && soap->recv_timeout)
1286  return 0;
1287  if (r < 0)
1288  {
1289  r = soap->errnum;
1290  if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
1291  return 0;
1292  }
1293  if (retries-- <= 0)
1294  return 0;
1295  }
1296  }
1297 #ifdef WITH_FASTCGI
1298  return fread(s, 1, n, stdin);
1299 #else
1300 #ifdef UNDER_CE
1301  return fread(s, 1, n, soap->recvfd);
1302 #else
1303 #ifdef WMW_RPM_IO
1304  if (soap->rpmreqid)
1305  r = httpBlockRead(soap->rpmreqid, s, n);
1306  else
1307 #endif
1308 #ifdef WIN32
1309  r = _read(soap->recvfd, s, (unsigned int)n);
1310 #else
1311  r = read(soap->recvfd, s, n);
1312 #endif
1313  if (r >= 0)
1314  return (size_t)r;
1315  soap->errnum = soap_errno;
1316  return 0;
1317 #endif
1318 #endif
1319 }
1320 #endif
1321 
1322 /******************************************************************************/
1323 
1324 #ifndef WITH_NOHTTP
1325 static soap_wchar
1327 {
1328  if (soap->bufidx < soap->buflen)
1329  return soap->buf[soap->bufidx++];
1330  soap->bufidx = 0;
1331  soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, sizeof(soap->buf));
1332  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, (int)soap->socket, soap->recvfd));
1333  DBGMSG(RECV, soap->buf, soap->buflen);
1334  if (soap->buflen)
1335  return soap->buf[soap->bufidx++];
1336  return EOF;
1337 }
1338 #endif
1339 
1340 /******************************************************************************/
1341 
1342 static int
1344 {
1345  return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
1346 }
1347 
1348 /******************************************************************************/
1349 
1350 SOAP_FMAC1
1351 int
1352 SOAP_FMAC2
1354 {
1355  size_t ret;
1356 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
1357  int r;
1358 #endif
1359 #ifdef WITH_ZLIB
1360  if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
1361  {
1362  if (soap->d_stream->next_out == Z_NULL)
1363  {
1364  soap->bufidx = soap->buflen = 0;
1365  return EOF;
1366  }
1367  if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
1368  {
1369  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
1370  soap->d_stream->next_out = (Byte*)soap->buf;
1371  soap->d_stream->avail_out = sizeof(soap->buf);
1373  if (r == Z_NEED_DICT && soap->z_dict)
1375  if (r == Z_OK || r == Z_STREAM_END)
1376  {
1377  soap->bufidx = 0;
1378  ret = soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out;
1380  soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
1381  if (r == Z_STREAM_END)
1382  {
1383  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1384  soap->d_stream->next_out = Z_NULL;
1385  }
1386  if (ret)
1387  {
1388  if (soap->count + ret < soap->count)
1389  return soap->error = SOAP_EOF;
1390  soap->count += ret;
1392  return soap->error = SOAP_EOF;
1393  soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1395  {
1396  soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)";
1397  return soap->error = SOAP_ZLIB_ERROR;
1398  }
1399  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1400  DBGMSG(RECV, soap->buf, ret);
1401  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
1402 #ifndef WITH_LEANER
1403  if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK)
1404  return soap->error = r;
1405 #endif
1406  return SOAP_OK;
1407  }
1408  }
1409  else if (r != Z_BUF_ERROR)
1410  {
1411  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
1412  soap->d_stream->next_out = Z_NULL;
1413  return soap->error = SOAP_ZLIB_ERROR;
1414  }
1415  }
1416 zlib_again:
1417  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
1418  {
1419  (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
1420  soap->buflen = soap->z_buflen;
1421  }
1422  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
1423  }
1424 #endif
1425 #ifndef WITH_NOHTTP
1426  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
1427  {
1428  for (;;)
1429  {
1430  soap_wchar c;
1431  char *t, tmp[17];
1432  if (soap->chunksize)
1433  {
1434  soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > sizeof(soap->buf) ? sizeof(soap->buf) : soap->chunksize);
1435  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
1436  DBGMSG(RECV, soap->buf, ret);
1437  soap->bufidx = 0;
1438  if (!ret)
1439  {
1440  soap->ahead = EOF;
1441  return EOF;
1442  }
1443  soap->chunksize -= ret;
1444  break;
1445  }
1446  if (!soap->chunkbuflen)
1447  {
1448  soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf));
1449  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, (int)soap->socket));
1450  DBGMSG(RECV, soap->buf, ret);
1451  soap->bufidx = 0;
1452  if (!ret)
1453  {
1454  soap->ahead = EOF;
1455  return EOF;
1456  }
1457  }
1458  else
1459  {
1460  soap->bufidx = soap->buflen;
1461  }
1463  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
1464  while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
1465  {
1466  if ((int)c == EOF)
1467  {
1468  soap->ahead = EOF;
1469  return EOF;
1470  }
1471  }
1472  t = tmp;
1473  do
1474  {
1475  *t++ = (char)c;
1476  } while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1);
1477  while ((int)c != EOF && c != '\n')
1479  if ((int)c == EOF)
1480  {
1481  soap->ahead = EOF;
1482  return EOF;
1483  }
1484  *t = '\0';
1485  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
1486  soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16);
1487  if (!soap->chunksize)
1488  {
1489  soap->bufidx = soap->buflen = soap->chunkbuflen = 0;
1490  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
1491  ret = 0;
1492  soap->ahead = EOF;
1493  break;
1494  }
1496  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
1497  if (soap->buflen > soap->chunkbuflen)
1498  {
1500  soap->chunksize -= soap->buflen - soap->bufidx;
1501  soap->chunkbuflen = 0;
1502  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
1503  }
1504  else if (soap->chunkbuflen)
1505  {
1506  soap->chunksize = 0;
1507  }
1508  ret = soap->buflen - soap->bufidx;
1509  if (ret)
1510  break;
1511  }
1512  }
1513  else
1514 #endif
1515  {
1516  soap->bufidx = 0;
1517  soap->buflen = ret = soap->frecv(soap, soap->buf, sizeof(soap->buf));
1518  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, (int)soap->socket, soap->recvfd));
1519  DBGMSG(RECV, soap->buf, ret);
1520  }
1521 #ifdef WITH_ZLIB
1522  if ((soap->mode & SOAP_ENC_ZLIB))
1523  {
1524  (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
1525  soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
1526  soap->d_stream->avail_in = (unsigned int)ret;
1527  soap->d_stream->next_out = (Byte*)soap->buf;
1528  soap->d_stream->avail_out = sizeof(soap->buf);
1530  if (r == Z_NEED_DICT && soap->z_dict)
1532  if (r == Z_OK || r == Z_STREAM_END)
1533  {
1534  soap->bufidx = 0;
1535  soap->z_buflen = soap->buflen;
1536  soap->buflen = sizeof(soap->buf) - soap->d_stream->avail_out;
1538  soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
1539  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
1540  if (ret && !soap->buflen && r != Z_STREAM_END)
1541  goto zlib_again;
1542  ret = soap->buflen;
1543  if (r == Z_STREAM_END)
1544  {
1545  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1546  soap->d_stream->next_out = Z_NULL;
1547  }
1548  soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1550  {
1551  soap->d_stream->msg = (char*)"caught SOAP_MINDEFLATERATIO explosive decompression guard (remedy: increase SOAP_MAXINFLATESIZE and/or decrease SOAP_MINDEFLATERATIO)";
1552  return soap->error = SOAP_ZLIB_ERROR;
1553  }
1554  DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1555  DBGMSG(RECV, soap->buf, ret);
1556 #ifndef WITH_LEANER
1557  if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)) != SOAP_OK)
1558  return soap->error = r;
1559 #endif
1560  }
1561  else
1562  {
1563  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
1564  soap->d_stream->next_out = Z_NULL;
1565  return soap->error = SOAP_ZLIB_ERROR;
1566  }
1567  }
1568 #endif
1569 #ifndef WITH_LEANER
1570  if (soap->fpreparerecv
1571 #ifdef WITH_ZLIB
1572  && soap->zlib_in == SOAP_ZLIB_NONE
1573 #endif
1574  && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
1575  return soap->error = r;
1576 #endif
1577  if (ret)
1578  {
1579  if (soap->count + ret < soap->count)
1580  return EOF;
1581  soap->count += ret;
1583  return EOF;
1584  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=" SOAP_ULONG_FORMAT " (+%lu)\n", soap->count, (unsigned long)ret));
1585  return SOAP_OK;
1586  }
1587  return EOF;
1588 }
1589 
1590 /******************************************************************************/
1591 
1592 SOAP_FMAC1
1593 int
1594 SOAP_FMAC2
1596 {
1597 #ifndef WITH_LEANER
1598  if ((soap->mode & SOAP_ENC_DIME))
1599  {
1600  if (soap->dime.buflen)
1601  {
1602  char *s;
1603  int i;
1604  unsigned char tmp[12];
1605  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked SOAP in DIME is in buffer\n"));
1606  soap->buflen = soap->dime.buflen;
1607  soap->dime.buflen = 0;
1608  soap->dime.chunksize = 0;
1609  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
1610  for (i = -(long)soap->dime.size&3; i > 0; i--)
1611  {
1612  soap->bufidx++;
1613  if (soap->bufidx >= soap->buflen)
1614  if (soap_recv_raw(soap))
1615  return EOF;
1616  }
1617  if (!(soap->dime.flags & SOAP_DIME_CF))
1618  return SOAP_OK;
1619  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next SOAP in DIME chunk\n"));
1620  s = (char*)tmp;
1621  for (i = 12; i > 0; i--)
1622  {
1623  *s++ = soap->buf[soap->bufidx++];
1624  if (soap->bufidx >= soap->buflen)
1625  if (soap_recv_raw(soap))
1626  return EOF;
1627  }
1628  if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
1629  return soap->error = SOAP_DIME_MISMATCH;
1630  soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
1631  soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
1632  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get SOAP in DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
1634  if (soap->buflen - soap->bufidx >= soap->dime.size)
1635  {
1636  if ((soap->dime.flags & SOAP_DIME_ME))
1637  {
1638  soap->mode &= ~SOAP_ENC_DIME;
1639  }
1640  else
1641  {
1642  soap->dime.buflen = soap->buflen;
1644  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n", (unsigned int)soap->buflen));
1645  }
1646  }
1647  else
1648  {
1650  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n", (unsigned int)soap->dime.chunksize));
1651  }
1652  return SOAP_OK;
1653  }
1654  if (soap->dime.chunksize)
1655  {
1656  if (soap_recv_raw(soap))
1657  return EOF;
1658  if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
1659  {
1660  if ((soap->dime.flags & SOAP_DIME_ME))
1661  {
1662  soap->dime.chunksize = 0;
1663  soap->mode &= ~SOAP_ENC_DIME;
1664  }
1665  else
1666  {
1667  soap->dime.buflen = soap->buflen;
1669  soap->dime.chunksize = 0;
1670  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes buffered)\n", (unsigned int)soap->buflen));
1671  }
1672  }
1673  else
1674  {
1676  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME (%u bytes in chunk left)\n", (unsigned int)soap->dime.chunksize));
1677  }
1678  return SOAP_OK;
1679  }
1680  }
1681  if (soap->ffilterrecv)
1682  {
1683  int err;
1684  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filter recverror = %d bufidx = %lu buflen = %lu\n", soap->recverror, (unsigned long)soap->bufidx, (unsigned long)soap->buflen));
1685  if (soap->recverror)
1686  {
1687  soap->bufidx = soap->buflen = 0;
1688  }
1689  else
1690  {
1691  soap->bufidx = soap->buflen = 0;
1692  err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf));
1693  if (err)
1694  {
1695  if (err == SOAP_EOF)
1696  return SOAP_EOF;
1697  return soap->error = err;
1698  }
1699  if (soap->buflen)
1700  {
1701  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filtered output continued %lu bytes\n", (unsigned long)soap->buflen));
1702  return SOAP_OK;
1703  }
1705  soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */
1706  }
1707  while (soap->ffilterrecv)
1708  {
1709  err = soap->ffilterrecv(soap, soap->buf + soap->bufidx, &soap->buflen, sizeof(soap->buf) - soap->bufidx);
1710  if (err)
1711  {
1712  if (err == SOAP_EOF)
1713  return SOAP_EOF;
1714  return soap->error = err;
1715  }
1716  if (soap->buflen)
1717  {
1718  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Filtered output %lu bytes\n", (unsigned long)soap->buflen));
1719  soap->buflen += soap->bufidx;
1720  return SOAP_OK;
1721  }
1722  if (soap->recverror)
1723  {
1724  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", soap->recverror));
1725  return soap->recverror;
1726  }
1728  soap->buflen -= soap->bufidx; /* chunked may set bufidx > 0 to skip hex chunk length */
1729  }
1730  }
1731  return soap->recverror = soap_recv_raw(soap);
1732 #else
1733  return soap_recv_raw(soap);
1734 #endif
1735 }
1736 
1737 /******************************************************************************/
1738 
1739 SOAP_FMAC1
1740 soap_wchar
1741 SOAP_FMAC2
1743 {
1744  soap_wchar c;
1745  c = soap->ahead;
1746  if (c)
1747  {
1748  if ((int)c != EOF)
1749  soap->ahead = 0;
1750  return c;
1751  }
1752  return soap_get1(soap);
1753 }
1754 
1755 /******************************************************************************/
1756 
1757 SOAP_FMAC1
1758 const struct soap_code_map*
1759 SOAP_FMAC2
1760 soap_code(const struct soap_code_map *code_map, const char *str)
1761 {
1762  if (code_map && str)
1763  {
1764  while (code_map->string)
1765  {
1766  if (!strcmp(str, code_map->string)) /* case sensitive */
1767  return code_map;
1768  code_map++;
1769  }
1770  }
1771  return NULL;
1772 }
1773 
1774 /******************************************************************************/
1775 
1776 SOAP_FMAC1
1777 LONG64
1778 SOAP_FMAC2
1779 soap_code_int(const struct soap_code_map *code_map, const char *str, LONG64 other)
1780 {
1781  if (code_map)
1782  {
1783  while (code_map->string)
1784  {
1785  if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
1786  return code_map->code;
1787  code_map++;
1788  }
1789  }
1790  return other;
1791 }
1792 
1793 /******************************************************************************/
1794 
1795 SOAP_FMAC1
1796 const char*
1797 SOAP_FMAC2
1798 soap_code_str(const struct soap_code_map *code_map, long code)
1799 {
1800  if (!code_map)
1801  return NULL;
1802  while (code_map->code != code && code_map->string)
1803  code_map++;
1804  return code_map->string;
1805 }
1806 
1807 /******************************************************************************/
1808 
1809 SOAP_FMAC1
1810 LONG64
1811 SOAP_FMAC2
1812 soap_code_bits(const struct soap_code_map *code_map, const char *str)
1813 {
1814  LONG64 bits = 0;
1815  if (code_map)
1816  {
1817  while (str && *str)
1818  {
1819  const struct soap_code_map *p;
1820  for (p = code_map; p->string; p++)
1821  {
1822  size_t n = strlen(p->string);
1823  if (!strncmp(p->string, str, n) && soap_coblank((soap_wchar)str[n]))
1824  {
1825  bits |= p->code;
1826  str += n;
1827  while (*str > 0 && *str <= 32)
1828  str++;
1829  break;
1830  }
1831  }
1832  if (!p->string)
1833  return 0;
1834  }
1835  }
1836  return bits;
1837 }
1838 
1839 /******************************************************************************/
1840 
1841 SOAP_FMAC1
1842 const char*
1843 SOAP_FMAC2
1844 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
1845 {
1846  char *t = soap->tmpbuf;
1847  if (code_map)
1848  {
1849  while (code_map->string)
1850  {
1851  if ((code_map->code & code))
1852  {
1853  const char *s = code_map->string;
1854  if (t != soap->tmpbuf)
1855  *t++ = ' ';
1856  while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1857  *t++ = *s++;
1858  if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1859  break;
1860  }
1861  code_map++;
1862  }
1863  }
1864  *t = '\0';
1865  return soap->tmpbuf;
1866 }
1867 
1868 /******************************************************************************/
1869 
1870 SOAP_FMAC1
1871 int
1872 SOAP_FMAC2
1873 soap_binary_search_string(const char **a, int n, const char *s)
1874 {
1875  int min = 0, max = n-1;
1876  while (min <= max)
1877  {
1878  int mid = (min+max)/2;
1879  int r = strcmp(s, a[mid]);
1880  if (r < 0)
1881  max = mid - 1;
1882  else if (r > 0)
1883  min = mid + 1;
1884  else
1885  return mid;
1886  }
1887  return -1;
1888 }
1889 
1890 /******************************************************************************/
1891 
1892 static soap_wchar
1894 {
1895  char tmp[8];
1896  int i;
1897  soap_wchar c;
1898  char *s = tmp;
1899  for (i = 0; i < (int)sizeof(tmp)-1; i++)
1900  {
1901  c = soap_get1(soap);
1902  if (c == ';' || (int)c == EOF)
1903  break;
1904  *s++ = (char)c;
1905  }
1906  *s = '\0';
1907  if (*tmp == '#')
1908  {
1909  if (tmp[1] == 'x' || tmp[1] == 'X')
1910  return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
1911  return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
1912  }
1913  if (!strcmp(tmp, "lt"))
1914  return '<';
1915  if (!strcmp(tmp, "gt"))
1916  return '>';
1917  if (!strcmp(tmp, "amp"))
1918  return '&';
1919  if (!strcmp(tmp, "quot"))
1920  return '"';
1921  if (!strcmp(tmp, "apos"))
1922  return '\'';
1923 #ifndef WITH_LEAN
1925 #else
1926  return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
1927 #endif
1928 }
1929 
1930 /******************************************************************************/
1931 
1932 #ifdef WITH_LEAN
1933 soap_wchar
1934 soap_get0(struct soap *soap)
1935 {
1936  if (soap->bufidx >= soap->buflen && soap_recv(soap))
1937  return EOF;
1938  return (unsigned char)soap->buf[soap->bufidx];
1939 }
1940 #endif
1941 
1942 /******************************************************************************/
1943 
1944 #ifdef WITH_LEAN
1945 soap_wchar
1946 soap_get1(struct soap *soap)
1947 {
1948  if (soap->bufidx >= soap->buflen && soap_recv(soap))
1949  return EOF;
1950  return (unsigned char)soap->buf[soap->bufidx++];
1951 }
1952 #endif
1953 
1954 /******************************************************************************/
1955 
1956 SOAP_FMAC1
1957 soap_wchar
1958 SOAP_FMAC2
1960 {
1961  soap_wchar c;
1962  c = soap->ahead;
1963  if (c)
1964  {
1965  if ((int)c != EOF)
1966  soap->ahead = 0;
1967  }
1968  else
1969  {
1970  c = soap_get1(soap);
1971  }
1972  while ((int)c != EOF)
1973  {
1974  if (soap->cdata)
1975  {
1976  if (c == ']')
1977  {
1978  c = soap_get1(soap);
1979  if (c == ']')
1980  {
1981  c = soap_get0(soap);
1982  if (c == '>')
1983  {
1984  soap->cdata = 0;
1985  c = soap_get1(soap);
1986  c = soap_get1(soap);
1987  }
1988  else
1989  {
1990  soap_unget(soap, ']');
1991  return ']';
1992  }
1993  }
1994  else
1995  {
1996  soap_revget1(soap);
1997  return ']';
1998  }
1999  }
2000  else
2001  {
2002  return c;
2003  }
2004  }
2005  switch (c)
2006  {
2007  case '<':
2008  do
2009  {
2010  c = soap_get1(soap);
2011  } while (soap_coblank(c));
2012  if (c == '!' || c == '?' || c == '%')
2013  {
2014  int k = 1;
2015  if (c == '!')
2016  {
2017  c = soap_get1(soap);
2018  if (c == '[')
2019  {
2020  do
2021  {
2022  c = soap_get1(soap);
2023  } while ((int)c != EOF && c != '[');
2024  if ((int)c == EOF)
2025  break;
2026  soap->cdata = 1;
2027  c = soap_get1(soap);
2028  continue;
2029  }
2030  if (c == '-' && (c = soap_get1(soap)) == '-')
2031  {
2032  do
2033  {
2034  c = soap_get1(soap);
2035  if (c == '-' && (c = soap_get1(soap)) == '-')
2036  break;
2037  } while ((int)c != EOF);
2038  }
2039  }
2040  else if (c == '?')
2041  {
2042  c = soap_getpi(soap);
2043  }
2044  while ((int)c != EOF)
2045  {
2046  if (c == '<')
2047  {
2048  k++;
2049  }
2050  else if (c == '>')
2051  {
2052  if (--k <= 0)
2053  break;
2054  }
2055  c = soap_get1(soap);
2056  }
2057  if ((int)c == EOF)
2058  break;
2059  c = soap_get1(soap);
2060  continue;
2061  }
2062  if (c == '/')
2063  return SOAP_TT;
2064  soap_revget1(soap);
2065  return SOAP_LT;
2066  case '>':
2067  return SOAP_GT;
2068  case '"':
2069  return SOAP_QT;
2070  case '\'':
2071  return SOAP_AP;
2072  case '&':
2073  return soap_char(soap) | 0x80000000;
2074  }
2075  break;
2076  }
2077  return c;
2078 }
2079 
2080 /******************************************************************************/
2081 
2082 static soap_wchar
2084 {
2085  char buf[64];
2086  char *s = buf;
2087  size_t i = sizeof(buf);
2088  soap_wchar c;
2089  while ((int)(c = soap_getchar(soap)) != EOF && c != '?')
2090  {
2091  if (i > 1)
2092  {
2093  if (soap_coblank(c))
2094  c = ' ';
2095  *s++ = (char)c;
2096  i--;
2097  }
2098  }
2099  *s = '\0';
2100  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
2101  if (!strncmp(buf, "xml ", 4))
2102  {
2103  s = strstr(buf, " encoding=");
2104  if (s && s[10])
2105  {
2106  if (!soap_tag_cmp(s + 11, "iso-8859-*")
2107  || !soap_tag_cmp(s + 11, "latin*"))
2108  {
2109  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin encoding\n"));
2110  soap->mode |= SOAP_ENC_LATIN;
2111  }
2112  else if (!soap_tag_cmp(s + 11, "utf-8*"))
2113  {
2114  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
2115  soap->mode &= ~SOAP_ENC_LATIN;
2116  }
2117  }
2118  }
2119  if ((int)c != EOF)
2120  c = soap_getchar(soap);
2121  return c;
2122 }
2123 
2124 /******************************************************************************/
2125 
2126 #ifndef WITH_LEANER
2127 SOAP_FMAC1
2128 int
2129 SOAP_FMAC2
2131 {
2132  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving " SOAP_ULONG_FORMAT " bytes forward\n", n));
2133  for (; n; n--)
2134  if ((int)soap_getchar(soap) == EOF)
2135  return SOAP_EOF;
2136  return SOAP_OK;
2137 }
2138 #endif
2139 
2140 /******************************************************************************/
2141 
2142 #ifndef WITH_LEANER
2143 SOAP_FMAC1
2144 ULONG64
2145 SOAP_FMAC2
2147 {
2148  return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
2149 }
2150 #endif
2151 
2152 /******************************************************************************/
2153 
2154 SOAP_FMAC1
2155 int
2156 SOAP_FMAC2
2157 soap_pututf8(struct soap *soap, unsigned long c)
2158 {
2159  char tmp[24];
2160  if ((c < 0x7F && c > 0x1F))
2161  {
2162  *tmp = (char)c;
2163  return soap_send_raw(soap, tmp, 1);
2164  }
2165 #ifdef WITH_REPLACE_ILLEGAL_UTF8
2166  if (!(c == 0x09 || c == 0x0A || c == 0x0D || (c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
2167  c = SOAP_UNKNOWN_UNICODE_CHAR;
2168 #endif
2169 #ifndef WITH_LEAN
2170  if (c > 0x9F)
2171  {
2172  char *t = tmp;
2173  if (c < 0x0800)
2174  {
2175  *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
2176  }
2177  else
2178  {
2179  if (c < 0x010000)
2180  {
2181  *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
2182  }
2183  else
2184  {
2185  if (c < 0x200000)
2186  {
2187  *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
2188  }
2189  else
2190  {
2191  if (c < 0x04000000)
2192  {
2193  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
2194  }
2195  else
2196  {
2197  *t++ = (char)(0xFC | ((c >> 30) & 0x01));
2198  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
2199  }
2200  *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
2201  }
2202  *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
2203  }
2204  *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
2205  }
2206  *t++ = (char)(0x80 | (c & 0x3F));
2207  *t = '\0';
2208  }
2209  else
2210 #endif
2211  (SOAP_SNPRINTF(tmp, sizeof(tmp), 20), "&#x%lX;", c);
2212  return soap_send(soap, tmp);
2213 }
2214 
2215 /******************************************************************************/
2216 
2217 SOAP_FMAC1
2218 soap_wchar
2219 SOAP_FMAC2
2221 {
2222 #ifdef WITH_REPLACE_ILLEGAL_UTF8
2223  soap_wchar c, c1, c2, c3;
2224 #else
2225  soap_wchar c, c1, c2, c3, c4;
2226 #endif
2227  c = soap->ahead;
2228  if (c >= 0x80)
2229  soap->ahead = 0;
2230  else
2231  c = (soap_wchar)soap_get(soap);
2232  if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN))
2233  return c;
2234 #ifdef WITH_REPLACE_ILLEGAL_UTF8
2235  c1 = (soap_wchar)soap_get1(soap);
2236  if (c <= 0xC1 || (c1 & 0xC0) != 0x80)
2237  {
2238  soap_revget1(soap);
2239  return SOAP_UNKNOWN_UNICODE_CHAR;
2240  }
2241  c1 &= 0x3F;
2242  if (c < 0xE0)
2243  return (((c & 0x1F) << 6) | c1);
2244  c2 = (soap_wchar)soap_get1(soap);
2245  if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80)
2246  {
2247  soap_revget1(soap);
2248  return SOAP_UNKNOWN_UNICODE_CHAR;
2249  }
2250  c2 &= 0x3F;
2251  if (c < 0xF0)
2252  return (((c & 0x0F) << 12) | (c1 << 6) | c2);
2253  c3 = (soap_wchar)soap_get1(soap);
2254  if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80)
2255  {
2256  soap_revget1(soap);
2257  return SOAP_UNKNOWN_UNICODE_CHAR;
2258  }
2259  return (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F));
2260 #else
2261  c1 = (soap_wchar)soap_get1(soap);
2262  if (c < 0xC0 || (c1 & 0xC0) != 0x80)
2263  {
2264  soap_revget1(soap);
2265  /* doesn't look like this is UTF-8, try continue as if ISO-8859-1 */
2266  return c;
2267  }
2268  c1 &= 0x3F;
2269  if (c < 0xE0)
2270  return ((soap_wchar)(c & 0x1F) << 6) | c1;
2271  c2 = (soap_wchar)soap_get1(soap) & 0x3F;
2272  if (c < 0xF0)
2273  return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
2274  c3 = (soap_wchar)soap_get1(soap) & 0x3F;
2275  if (c < 0xF8)
2276  return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
2277  c4 = (soap_wchar)soap_get1(soap) & 0x3F;
2278  if (c < 0xFC)
2279  return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
2280  return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
2281 #endif
2282 }
2283 
2284 /******************************************************************************/
2285 
2286 SOAP_FMAC1
2287 size_t
2288 SOAP_FMAC2
2289 soap_utf8len(const char *s)
2290 {
2291  size_t l = 0;
2292  while (*s)
2293  if ((*s++ & 0xC0) != 0x80)
2294  l++;
2295  return l;
2296 }
2297 
2298 /******************************************************************************/
2299 
2300 SOAP_FMAC1
2301 int
2302 SOAP_FMAC2
2303 soap_puthex(struct soap *soap, const unsigned char *s, int n)
2304 {
2305  char d[2 * SOAP_BINARY_BUFLEN], *p = d;
2306 #ifdef WITH_DOM
2307  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2308  {
2309  soap->dom->text = soap_s2hex(soap, s, NULL, n);
2310  if (!soap->dom->text)
2311  return soap->error;
2312  return SOAP_OK;
2313  }
2314 #endif
2315  for (; n > 0; n--)
2316  {
2317  int m = *s++;
2318  p[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
2319  m &= 0x0F;
2320  p[1] = (char)(m + (m > 9 ? '7' : '0'));
2321  p += 2;
2322  if (p - d == sizeof(d))
2323  {
2324  if (soap_send_raw(soap, d, sizeof(d)))
2325  return soap->error;
2326  p = d;
2327  }
2328  }
2329  if (p != d && soap_send_raw(soap, d, p - d))
2330  return soap->error;
2331  return SOAP_OK;
2332 }
2333 
2334 /******************************************************************************/
2335 
2336 SOAP_FMAC1
2337 unsigned char*
2338 SOAP_FMAC2
2339 soap_gethex(struct soap *soap, int *n)
2340 {
2341  size_t l = 0;
2342 #ifdef WITH_DOM
2343  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2344  {
2345  soap->dom->text = soap_string_in(soap, 0, -1, -1, NULL);
2346  return (unsigned char*)soap_hex2s(soap, soap->dom->text, NULL, 0, n);
2347  }
2348 #endif
2349 #ifdef WITH_FAST
2350  soap->labidx = 0;
2351  for (;;)
2352  {
2353  char *s;
2354  size_t i, k;
2355  if (soap_append_lab(soap, NULL, 0))
2356  return NULL;
2357  s = soap->labbuf + soap->labidx;
2358  k = soap->lablen - soap->labidx;
2359  soap->labidx = soap->lablen;
2360  for (i = 0; i < k; i++)
2361  {
2362  char d1, d2;
2363  soap_wchar c;
2364  c = soap_get(soap);
2365  if (soap_isxdigit(c))
2366  {
2367  d1 = (char)c;
2368  c = soap_get(soap);
2369  if (soap_isxdigit(c))
2370  {
2371  d2 = (char)c;
2372  }
2373  else
2374  {
2375  soap->error = SOAP_TYPE;
2376  return NULL;
2377  }
2378  }
2379  else
2380  {
2381  unsigned char *p = NULL;
2382  l = soap->lablen + i - k;
2383  soap_unget(soap, c);
2384  if (n)
2385  *n = (int)l;
2386  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2387  {
2388  soap->error = SOAP_LENGTH;
2389  }
2390  else
2391  {
2392  p = (unsigned char*)soap_malloc(soap, l);
2393  if (p)
2394  (void)soap_memcpy((void*)p, l, (const void*)soap->labbuf, l);
2395  }
2396  return p;
2397  }
2398  *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
2399  }
2400  l = soap->lablen;
2401  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2402  {
2403  soap->error = SOAP_LENGTH;
2404  return NULL;
2405  }
2406  }
2407 #else
2408  if (soap_alloc_block(soap) == NULL)
2409  return NULL;
2410  for (;;)
2411  {
2412  int i;
2413  char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
2414  if (!s)
2415  {
2417  return NULL;
2418  }
2419  for (i = 0; i < SOAP_BLKLEN; i++)
2420  {
2421  char d1, d2;
2423  if (soap_isxdigit(c))
2424  {
2425  d1 = (char)c;
2426  c = soap_get(soap);
2427  if (soap_isxdigit(c))
2428  d2 = (char)c;
2429  else
2430  {
2432  soap->error = SOAP_TYPE;
2433  return NULL;
2434  }
2435  }
2436  else
2437  {
2438  unsigned char *p;
2439  soap_unget(soap, c);
2440  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2441  {
2442  soap->error = SOAP_LENGTH;
2444  return NULL;
2445  }
2446  if (n)
2447  *n = (int)soap_size_block(soap, NULL, i);
2448  p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0);
2449  return p;
2450  }
2451  *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
2452  l++;
2453  }
2454  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2455  {
2456  soap->error = SOAP_LENGTH;
2458  return NULL;
2459  }
2460  }
2461 #endif
2462 }
2463 
2464 /******************************************************************************/
2465 
2466 SOAP_FMAC1
2467 int
2468 SOAP_FMAC2
2469 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
2470 {
2471  char d[4 * SOAP_BINARY_BUFLEN], *p = d;
2472  if (!s)
2473  return SOAP_OK;
2474 #ifdef WITH_DOM
2475  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2476  {
2477  soap->dom->text = soap_s2base64(soap, s, NULL, n);
2478  if (!soap->dom->text)
2479  return soap->error;
2480  return SOAP_OK;
2481  }
2482 #endif
2483  for (; n > 2; n -= 3, s += 3)
2484  {
2485  p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
2486  p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)];
2487  p[2] = soap_base64o[((s[1] & 0x0F) << 2) | ((s[2] & 0xC0) >> 6)];
2488  p[3] = soap_base64o[s[2] & 0x3F];
2489  p += 4;
2490  if (p - d == sizeof(d))
2491  {
2492  if (soap_send_raw(soap, d, sizeof(d)))
2493  return soap->error;
2494  p = d;
2495  }
2496  }
2497  if (n == 2)
2498  {
2499  p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
2500  p[1] = soap_base64o[((s[0] & 0x03) << 4) | ((s[1] & 0xF0) >> 4)];
2501  p[2] = soap_base64o[(s[1] & 0x0F) << 2];
2502  p[3] = '=';
2503  p += 4;
2504  }
2505  else if (n == 1)
2506  {
2507  p[0] = soap_base64o[(s[0] & 0xFC) >> 2];
2508  p[1] = soap_base64o[(s[0] & 0x03) << 4];
2509  p[2] = '=';
2510  p[3] = '=';
2511  p += 4;
2512  }
2513  if (p != d && soap_send_raw(soap, d, p - d))
2514  return soap->error;
2515  return SOAP_OK;
2516 }
2517 
2518 /******************************************************************************/
2519 
2520 SOAP_FMAC1
2521 unsigned char*
2522 SOAP_FMAC2
2523 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
2524 {
2525  size_t l = 0;
2526  (void)malloc_flag;
2527 #ifdef WITH_DOM
2528  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
2529  {
2530  soap->dom->text = soap_string_in(soap, 0, -1, -1, NULL);
2531  return (unsigned char*)soap_base642s(soap, soap->dom->text, NULL, 0, n);
2532  }
2533 #endif
2534 #ifdef WITH_FAST
2535  soap->labidx = 0;
2536  for (;;)
2537  {
2538  size_t i, k;
2539  char *s;
2540  if (soap_append_lab(soap, NULL, 2))
2541  return NULL;
2542  s = soap->labbuf + soap->labidx;
2543  k = soap->lablen - soap->labidx;
2544  soap->labidx = 3 * (soap->lablen / 3);
2545  if (k > 2)
2546  {
2547  for (i = 0; i < k - 2; i += 3)
2548  {
2549  unsigned long m = 0;
2550  int j = 0;
2551  do
2552  {
2554  if (c < SOAP_AP)
2555  c &= 0x7FFFFFFF;
2556  if (c == '=' || c < 0)
2557  {
2558  unsigned char *p = NULL;
2559  switch (j)
2560  {
2561  case 2:
2562  *s++ = (char)((m >> 4) & 0xFF);
2563  i++;
2564  break;
2565  case 3:
2566  *s++ = (char)((m >> 10) & 0xFF);
2567  *s++ = (char)((m >> 2) & 0xFF);
2568  i += 2;
2569  }
2570  l = soap->lablen + i - k;
2571  if (n)
2572  *n = (int)l;
2573  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2574  soap->error = SOAP_LENGTH;
2575  else
2576  {
2577  p = (unsigned char*)soap_malloc(soap, l);
2578  if (p)
2579  (void)soap_memcpy((void*)p, l, (const void*)soap->labbuf, l);
2580  }
2581  if (c >= 0)
2582  {
2583  while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
2584  continue;
2585  }
2586  soap_unget(soap, c);
2587  return p;
2588  }
2589  c -= '+';
2590  if (c >= 0 && c <= 79)
2591  {
2592  int b = soap_base64i[c];
2593  if (b >= 64)
2594  {
2595  soap->error = SOAP_TYPE;
2596  return NULL;
2597  }
2598  m = (m << 6) + b;
2599  j++;
2600  }
2601  else if (!soap_coblank(c + '+'))
2602  {
2603  soap->error = SOAP_TYPE;
2604  return NULL;
2605  }
2606  } while (j < 4);
2607  *s++ = (char)((m >> 16) & 0xFF);
2608  *s++ = (char)((m >> 8) & 0xFF);
2609  *s++ = (char)(m & 0xFF);
2610  }
2611  l = soap->lablen;
2612  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2613  {
2614  soap->error = SOAP_LENGTH;
2615  return NULL;
2616  }
2617  }
2618  }
2619 #else
2620  if (soap_alloc_block(soap) == NULL)
2621  return NULL;
2622  for (;;)
2623  {
2624  int i;
2625  char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
2626  if (!s)
2627  {
2629  return NULL;
2630  }
2631  for (i = 0; i < SOAP_BLKLEN; i++)
2632  {
2633  unsigned long m = 0;
2634  int j = 0;
2635  do
2636  {
2638  if (c < SOAP_AP)
2639  c &= 0x7FFFFFFF;
2640  if (c == '=' || c < 0)
2641  {
2642  unsigned char *p;
2643  i *= 3;
2644  switch (j)
2645  {
2646  case 2:
2647  *s++ = (char)((m >> 4) & 0xFF);
2648  i++;
2649  l++;
2650  break;
2651  case 3:
2652  *s++ = (char)((m >> 10) & 0xFF);
2653  *s++ = (char)((m >> 2) & 0xFF);
2654  l += 2;
2655  i += 2;
2656  }
2657  if (n)
2658  *n = (int)soap_size_block(soap, NULL, i);
2659  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2660  {
2661  soap->error = SOAP_LENGTH;
2663  return NULL;
2664  }
2665  p = (unsigned char*)soap_save_block(soap, NULL, NULL, 0);
2666  if (c >= 0)
2667  {
2668  while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
2669  continue;
2670  }
2671  soap_unget(soap, c);
2672  return p;
2673  }
2674  c -= '+';
2675  if (c >= 0 && c <= 79)
2676  {
2677  int b = soap_base64i[c];
2678  if (b >= 64)
2679  {
2680  soap->error = SOAP_TYPE;
2681  return NULL;
2682  }
2683  m = (m << 6) + b;
2684  j++;
2685  }
2686  else if (!soap_coblank(c + '+'))
2687  {
2688  soap->error = SOAP_TYPE;
2689  return NULL;
2690  }
2691  } while (j < 4);
2692  *s++ = (char)((m >> 16) & 0xFF);
2693  *s++ = (char)((m >> 8) & 0xFF);
2694  *s++ = (char)(m & 0xFF);
2695  l += 3;
2696  }
2697  if (soap->maxlength > 0 && l > (size_t)soap->maxlength)
2698  {
2699  soap->error = SOAP_LENGTH;
2701  return NULL;
2702  }
2703  }
2704 #endif
2705 }
2706 
2707 /******************************************************************************/
2708 
2709 #ifndef WITH_LEANER
2710 SOAP_FMAC1
2711 int
2712 SOAP_FMAC2
2713 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2714 {
2715  /* Check MTOM xop:Include element (within hex/base64Binary) */
2716  /* TODO: this code to be obsoleted with new import/xop.h conventions */
2717  short body = soap->body; /* should save type too? */
2718  if (!soap_peek_element(soap))
2719  {
2720  if (!soap_element_begin_in(soap, ":Include", 0, NULL))
2721  {
2722  if (soap_attachment_forward(soap, ptr, size, id, type, options)
2723  || (soap->body && soap_element_end_in(soap, ":Include")))
2724  return soap->error;
2725  }
2726  else if (soap->error == SOAP_TAG_MISMATCH)
2727  soap_retry(soap);
2728  else
2729  return soap->error;
2730  }
2731  soap->body = body;
2732  return SOAP_OK;
2733 }
2734 #endif
2735 
2736 /******************************************************************************/
2737 
2738 #ifndef WITH_LEANER
2739 SOAP_FMAC1
2740 int
2741 SOAP_FMAC2
2742 soap_attachment_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2743 {
2744  struct soap_xlist *xp;
2745  *ptr = NULL;
2746  *size = 0;
2747  *id = NULL;
2748  *type = NULL;
2749  *options = NULL;
2750  if (!*soap->href)
2751  return SOAP_OK;
2752  *id = soap_strdup(soap, soap->href);
2753  xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
2754  if (!xp)
2755  return soap->error = SOAP_EOM;
2756  xp->next = soap->xlist;
2757  xp->ptr = ptr;
2758  xp->size = size;
2759  xp->id = *id;
2760  xp->type = type;
2761  xp->options = options;
2762  soap->xlist = xp;
2763  return SOAP_OK;
2764 }
2765 #endif
2766 
2767 /******************************************************************************/
2768 
2769 SOAP_FMAC1
2770 void *
2771 SOAP_FMAC2
2772 soap_memdup(struct soap *soap, const void *s, size_t n)
2773 {
2774  void *t = NULL;
2775  if (s)
2776  {
2777  t = soap_malloc(soap, n);
2778  if (t)
2779  (void)soap_memcpy(t, n, s, n);
2780  }
2781  return t;
2782 }
2783 
2784 /******************************************************************************/
2785 
2786 SOAP_FMAC1
2787 char *
2788 SOAP_FMAC2
2789 soap_strdup(struct soap *soap, const char *s)
2790 {
2791  char *t = NULL;
2792  if (s)
2793  {
2794  size_t n = strlen(s) + 1;
2795  if (n > 0)
2796  {
2797  t = (char*)soap_malloc(soap, n);
2798  if (t)
2799  {
2800  (void)soap_memcpy((void*)t, n, (const void*)s, n);
2801  t[n - 1] = '\0';
2802  }
2803  }
2804  }
2805  return t;
2806 }
2807 
2808 /******************************************************************************/
2809 
2810 SOAP_FMAC1
2811 wchar_t *
2812 SOAP_FMAC2
2813 soap_wstrdup(struct soap *soap, const wchar_t *s)
2814 {
2815  wchar_t *t = NULL;
2816  if (s)
2817  {
2818  size_t n = 0, m;
2819  while (s[n])
2820  n++;
2821  n++;
2822  m = sizeof(wchar_t) * n;
2823  if (n > 0)
2824  {
2825  t = (wchar_t*)soap_malloc(soap, m);
2826  if (t)
2827  {
2828  (void)soap_memcpy((void*)t, m, (const void*)s, m);
2829  t[n - 1] = L'\0';
2830  }
2831  }
2832  }
2833  return t;
2834 }
2835 
2836 /******************************************************************************/
2837 
2838 SOAP_FMAC1
2839 char *
2840 SOAP_FMAC2
2841 soap_strtrim(struct soap *soap, char *s)
2842 {
2843  (void)soap;
2844  if (s)
2845  {
2846  char *t;
2847  while ((*s >= 9 && *s <= 13) || *s == 32)
2848  s++;
2849  t = s;
2850  while (*t)
2851  t++;
2852  while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32))
2853  continue;
2854  t[1] = '\0';
2855  }
2856  return s;
2857 }
2858 
2859 /******************************************************************************/
2860 
2861 SOAP_FMAC1
2862 wchar_t *
2863 SOAP_FMAC2
2864 soap_wstrtrim(struct soap *soap, wchar_t *s)
2865 {
2866  (void)soap;
2867  if (s)
2868  {
2869  wchar_t *t;
2870  while ((*s >= 9 && *s <= 13) || *s == 32)
2871  s++;
2872  t = s;
2873  while (*t)
2874  t++;
2875  while (--t > s && ((*t >= 9 && *t <= 13) || *t == 32))
2876  continue;
2877  t[1] = L'\0';
2878  }
2879  return s;
2880 }
2881 
2882 /******************************************************************************/
2883 
2884 SOAP_FMAC1
2885 struct soap_blist*
2886 SOAP_FMAC2
2888 {
2889  struct soap_blist *p;
2890  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", (void*)soap->blist));
2891  p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist));
2892  if (!p)
2893  {
2894  soap->error = SOAP_EOM;
2895  return NULL;
2896  }
2897  p->next = soap->blist;
2898  p->head = NULL;
2899  p->size = 0;
2900  p->item = 0;
2901  soap->blist = p;
2902  return p;
2903 }
2904 
2905 /******************************************************************************/
2906 
2907 SOAP_FMAC1
2908 void*
2909 SOAP_FMAC2
2910 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
2911 {
2912  struct soap_bhead *p;
2913  if (!b)
2914  b = soap->blist;
2915  if (!b
2916  || b->size + n < b->size
2917  || sizeof(struct soap_bhead) + n < n
2918  || (SOAP_MAXALLOCSIZE > 0 && sizeof(struct soap_bhead) + n > SOAP_MAXALLOCSIZE))
2919  {
2920  soap->error = SOAP_EOM;
2921  return NULL;
2922  }
2923  p = (struct soap_bhead*)SOAP_MALLOC(soap, sizeof(struct soap_bhead) + n);
2924  if (!p)
2925  {
2926  soap->error = SOAP_EOM;
2927  return NULL;
2928  }
2929  p->next = b->head;
2930  b->head = p;
2931  p->size = n;
2932  b->size += n;
2933  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block %p of %u bytes on %lu previous blocks (%lu bytes total)\n", (void*)p, (unsigned int)n, (unsigned long)b->item, (unsigned long)b->size));
2934  b->item++;
2935  return (void*)(p + 1); /* skip block header and point to n allocated bytes */
2936 }
2937 
2938 /******************************************************************************/
2939 
2940 SOAP_FMAC1
2941 void*
2942 SOAP_FMAC2
2943 soap_push_block_max(struct soap *soap, struct soap_blist *b, size_t n)
2944 {
2945  if (b && b->item >= soap->maxoccurs) /* restrict block array length */
2946  {
2947  soap->error = SOAP_OCCURS;
2948  return NULL;
2949  }
2950  return soap_push_block(soap, b, n);
2951 }
2952 
2953 /******************************************************************************/
2954 
2955 SOAP_FMAC1
2956 void
2957 SOAP_FMAC2
2959 {
2960  struct soap_bhead *p;
2961  if (!b)
2962  b = soap->blist;
2963  if (!b || !b->head)
2964  return;
2965  p = b->head;
2966  b->size -= p->size;
2967  b->head = p->next;
2968  b->item--;
2969  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block %p (%lu items of %lu bytes total)\n", (void*)p, (unsigned long)b->item, (unsigned long)b->size));
2970  SOAP_FREE(soap, p);
2971 }
2972 
2973 /******************************************************************************/
2974 
2975 SOAP_FMAC1
2976 void
2977 SOAP_FMAC2
2978 soap_update_pointers(struct soap *soap, const char *dst, const char *src, size_t len)
2979 {
2980  const void *start = src, *end = src + len;
2981 #ifndef WITH_LEANER
2982  struct soap_xlist *xp;
2983 #endif
2984 #ifndef WITH_NOIDREF
2985  if ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH))
2986  {
2987  int i;
2988  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update pointers %p (%lu bytes) -> %p\n", (void*)src, (unsigned long)len, (void*)dst));
2989  for (i = 0; i < SOAP_IDHASH; i++)
2990  {
2991  struct soap_ilist *ip;
2992  for (ip = soap->iht[i]; ip; ip = ip->next)
2993  {
2994  struct soap_flist *fp;
2995  void *p, **q;
2996  if (ip->shaky)
2997  {
2998  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update shaky id='%s'\n", ip->id));
2999  if (ip->ptr && ip->ptr >= start && ip->ptr < end)
3000  {
3001  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update ptr %p -> %p\n", ip->ptr, (void*)((const char*)ip->ptr + (dst-src))));
3002  ip->ptr = (void*)((const char*)ip->ptr + (dst-src));
3003  }
3004  for (q = &ip->link; q; q = (void**)p)
3005  {
3006  p = *q;
3007  if (p && p >= start && p < end)
3008  {
3009  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p -> %p\n", ip->id, p, (void*)((const char*)p + (dst-src))));
3010  *q = (void*)((const char*)p + (dst-src));
3011  }
3012  }
3013  for (q = &ip->copy; q; q = (void**)p)
3014  {
3015  p = *q;
3016  if (p && p >= start && p < end)
3017  {
3018  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p -> %p\n", ip->id, p, (void*)((const char*)p + (dst-src))));
3019  *q = (void*)((const char*)p + (dst-src));
3020  }
3021  }
3022  for (fp = ip->flist; fp; fp = fp->next)
3023  {
3024  if (fp->ptr >= start && fp->ptr < end)
3025  {
3026  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' target type=%d %p -> %p\n", ip->id, fp->type, fp->ptr, (void*)((char*)fp->ptr + (dst-src))));
3027  fp->ptr = (void*)((const char*)fp->ptr + (dst-src));
3028  }
3029  }
3030  if (ip->smart && ip->smart >= start && ip->smart < end)
3031  {
3032  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Smart shared pointer update %p -> %p\n", ip->smart, (void*)((const char*)ip->smart + (dst-src))));
3033  ip->smart = (void*)((const char*)ip->smart + (dst-src));
3034  }
3035  }
3036  }
3037  }
3038  }
3039 #else
3040  (void)soap; (void)start; (void)end; (void)dst; (void)src;
3041 #endif
3042 #ifndef WITH_LEANER
3043  for (xp = soap->xlist; xp; xp = xp->next)
3044  {
3045  if (xp->ptr && (void*)xp->ptr >= start && (void*)xp->ptr < end)
3046  {
3047  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update attachment id='%s' %p -> %p\n", xp->id ? xp->id : SOAP_STR_EOS, (void*)xp->ptr, (void*)((char*)xp->ptr + (dst-src))));
3048  xp->ptr = (unsigned char**)((char*)xp->ptr + (dst-src));
3049  xp->size = (int*)((char*)xp->size + (dst-src));
3050  xp->type = (char**)((char*)xp->type + (dst-src));
3051  xp->options = (char**)((char*)xp->options + (dst-src));
3052  }
3053  }
3054 #endif
3055 }
3056 
3057 /******************************************************************************/
3058 
3059 #ifndef WITH_NOIDREF
3060 static int
3061 soap_has_copies(struct soap *soap, const char *start, const char *end)
3062 {
3063  int i;
3064  struct soap_ilist *ip = NULL;
3065  struct soap_flist *fp = NULL;
3066  const char *p;
3067  for (i = 0; i < SOAP_IDHASH; i++)
3068  {
3069  for (ip = soap->iht[i]; ip; ip = ip->next)
3070  {
3071  for (p = (const char*)ip->copy; p; p = *(const char**)p)
3072  if (p >= start && p < end)
3073  return SOAP_ERR;
3074  for (fp = ip->flist; fp; fp = fp->next)
3075  if (fp->type == ip->type && (const char*)fp->ptr >= start && (const char*)fp->ptr < end)
3076  return SOAP_ERR;
3077  }
3078  }
3079  return SOAP_OK;
3080 }
3081 #endif
3082 
3083 /******************************************************************************/
3084 
3085 #ifndef WITH_NOIDREF
3086 SOAP_FMAC1
3087 int
3088 SOAP_FMAC2
3090 {
3091  int i;
3092  short flag;
3093  const char *id;
3094  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded refs\n"));
3095  for (i = 0; i < SOAP_IDHASH; i++)
3096  {
3097  struct soap_ilist *ip;
3098  for (ip = soap->iht[i]; ip; ip = ip->next)
3099  {
3100  if (ip->ptr)
3101  {
3102  void **q;
3103  struct soap_flist *fp, **fpp = &ip->flist;
3104  if (ip->spine)
3105  ip->spine[0] = ip->ptr;
3106  q = (void**)ip->link;
3107  ip->link = NULL;
3108  DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type));
3109  while (q)
3110  {
3111  void *p = *q;
3112  *q = ip->ptr;
3113  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void*)q, ip->ptr));
3114  q = (void**)p;
3115  }
3116  while ((fp = *fpp))
3117  {
3118  if (fp->level > 0 && fp->finsert)
3119  {
3120  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... insert type=%d link %p -> %p\n", fp->type, fp->ptr, ip->ptr));
3121  if (ip->spine && fp->level <= SOAP_MAXPTRS)
3122  fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1], &ip->smart);
3123  else if (fp->level == 1)
3124  fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->ptr, &ip->smart);
3125  else if (fp->level <= SOAP_MAXPTRS)
3126  {
3127  int i;
3128  ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*));
3129  if (!ip->spine)
3130  return soap->error = SOAP_EOM;
3131  ip->spine[0] = ip->ptr;
3132  for (i = 1; i < SOAP_MAXPTRS; i++)
3133  ip->spine[i] = &ip->spine[i - 1];
3134  fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, &ip->spine[fp->level - 1], &ip->smart);
3135  }
3136  *fpp = fp->next;
3137  SOAP_FREE(soap, fp);
3138  }
3139  else
3140  fpp = &fp->next;
3141  }
3142  }
3143  else if (*ip->id == '#')
3144  {
3145  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing id='%s'\n", ip->id));
3146  soap_strcpy(soap->id, sizeof(soap->id), ip->id + 1);
3147  return soap->error = SOAP_MISSING_ID;
3148  }
3149  }
3150  }
3151  do
3152  {
3153  flag = 0;
3154  id = NULL;
3155  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
3156  for (i = 0; i < SOAP_IDHASH; i++)
3157  {
3158  struct soap_ilist *ip;
3159  for (ip = soap->iht[i]; ip; ip = ip->next)
3160  {
3161  if (ip->copy || ip->flist)
3162  {
3163  if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
3164  {
3165  struct soap_flist *fp;
3166  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving id='%s' type=%d ptr=%p size=%lu ...\n", ip->id, ip->type, ip->ptr, (unsigned long)ip->size));
3167  if (ip->copy)
3168  {
3169  void *p, **q = (void**)ip->copy;
3170  DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
3171  ip->copy = NULL;
3172  do
3173  {
3174  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, (void*)q, (unsigned int)ip->size));
3175  p = *q;
3176  (void)soap_memcpy((void*)q, ip->size, (const void*)ip->ptr, ip->size);
3177  q = (void**)p;
3178  } while (q);
3179  flag = 1;
3180  }
3181  while ((fp = ip->flist))
3182  {
3183  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d target type=%d location=%p level=%u id='%s'\n", ip->type, fp->type, ip->ptr, fp->level, ip->id));
3184  if (fp->level == 0)
3185  {
3186  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%lu bytes)\n", ip->ptr, fp->ptr, (unsigned long)ip->size));
3187  if (fp->finsert)
3188  fp->finsert(soap, ip->type, fp->type, fp->ptr, fp->index, ip->ptr, &ip->smart);
3189  else
3190  (void)soap_memcpy((void*)fp->ptr, ip->size, (const void*)ip->ptr, ip->size);
3191  }
3192  ip->flist = fp->next;
3193  SOAP_FREE(soap, fp);
3194  flag = 1;
3195  }
3196  }
3197  else if (*ip->id == '#')
3198  id = ip->id;
3199  }
3200  }
3201  }
3202  } while (flag);
3203  if (id)
3204  {
3205  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the gSOAP developers\n", id));
3206  return soap_id_nullify(soap, id);
3207  }
3208  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
3209  return SOAP_OK;
3210 }
3211 #endif
3212 
3213 /******************************************************************************/
3214 
3215 SOAP_FMAC1
3216 size_t
3217 SOAP_FMAC2
3218 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
3219 {
3220  if (!b)
3221  b = soap->blist;
3222  if (b->head)
3223  {
3224  b->size -= b->head->size - n;
3225  b->head->size = n;
3226  }
3227  return b->size;
3228 }
3229 
3230 /******************************************************************************/
3231 
3232 SOAP_FMAC1
3233 char*
3234 SOAP_FMAC2
3236 {
3237  struct soap_bhead *p, *q, *r;
3238  if (!b)
3239  b = soap->blist;
3240  p = b->head;
3241  if (!p)
3242  return NULL;
3243  r = NULL;
3244  do
3245  {
3246  q = p->next;
3247  p->next = r;
3248  r = p;
3249  p = q;
3250  } while (p);
3251  b->head = r;
3252  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block %p\n", (void*)(r + 1)));
3253  return (char*)(r + 1);
3254 }
3255 
3256 /******************************************************************************/
3257 
3258 SOAP_FMAC1
3259 char*
3260 SOAP_FMAC2
3262 {
3263  struct soap_bhead *p;
3264  if (!b)
3265  b = soap->blist;
3266  p = b->head;
3267  if (p)
3268  {
3269  b->head = p->next;
3270  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block %p, deleting current block\n", (void*)(b->head ? b->head + 1 : NULL)));
3271  SOAP_FREE(soap, p);
3272  if (b->head)
3273  return (char*)(b->head + 1);
3274  }
3275  return NULL;
3276 }
3277 
3278 /******************************************************************************/
3279 
3280 SOAP_FMAC1
3281 size_t
3282 SOAP_FMAC2
3284 {
3285  if (!b)
3286  b = soap->blist;
3287  return b->head->size;
3288 }
3289 
3290 /******************************************************************************/
3291 
3292 SOAP_FMAC1
3293 void
3294 SOAP_FMAC2
3296 {
3297  struct soap_bhead *p, *q;
3298  if (!b)
3299  b = soap->blist;
3300  if (b)
3301  {
3302  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
3303  for (p = b->head; p; p = q)
3304  {
3305  q = p->next;
3306  SOAP_FREE(soap, p);
3307  }
3308  if (soap->blist == b)
3309  soap->blist = b->next;
3310  else
3311  {
3312  struct soap_blist *bp;
3313  for (bp = soap->blist; bp; bp = bp->next)
3314  {
3315  if (bp->next == b)
3316  {
3317  bp->next = b->next;
3318  break;
3319  }
3320  }
3321  }
3322  SOAP_FREE(soap, b);
3323  }
3324  DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restored previous block sequence\n"));
3325 #ifndef WITH_NOIDREF
3326  if (!soap->blist && ((soap->version && !(soap->imode & SOAP_XML_TREE)) || (soap->mode & SOAP_XML_GRAPH)))
3327  {
3328  int i;
3329  struct soap_ilist *ip = NULL;
3330  for (i = 0; i < SOAP_IDHASH; i++)
3331  for (ip = soap->iht[i]; ip; ip = ip->next)
3332  ip->shaky = 0;
3333  }
3334 #endif
3335 }
3336 
3337 /******************************************************************************/
3338 
3339 SOAP_FMAC1
3340 char*
3341 SOAP_FMAC2
3342 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
3343 {
3344  size_t n;
3345  char *q, *s;
3346  if (!b)
3347  b = soap->blist;
3348  if (b->size)
3349  {
3350  if (!p)
3351  p = (char*)soap_malloc(soap, b->size);
3352  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all %lu blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned long)b->item, (unsigned int)b->size, (void*)b->head, (void*)p));
3353  if (p)
3354  {
3355  s = p;
3356  for (q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
3357  {
3358  n = soap_block_size(soap, b);
3359  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, (void*)q, (void*)s));
3360  if (flag)
3361  soap_update_pointers(soap, s, q, n);
3362  (void)soap_memcpy((void*)s, n, (const void*)q, n);
3363  s += n;
3364  }
3365  }
3366  else
3367  soap->error = SOAP_EOM;
3368  }
3369  soap_end_block(soap, b);
3370  return p;
3371 }
3372 
3373 /******************************************************************************/
3374 
3375 SOAP_FMAC1
3376 char *
3377 SOAP_FMAC2
3378 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
3379 {
3380  int i;
3381  const char *t = ",%d";
3382  if (!type)
3383  return NULL;
3384  if (soap->version == 2)
3385  t = " %d";
3386  if (soap->version != 2 && offset)
3387  {
3388  (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0] + offset[0]);
3389  for (i = 1; i < dim; i++)
3390  {
3391  size_t l = strlen(soap->type);
3392  (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i] + offset[i]);
3393  }
3394  }
3395  else
3396  {
3397  (SOAP_SNPRINTF(soap->type, sizeof(soap->type) - 1, strlen(type) + 20), "%s[%d", type, size[0]);
3398  for (i = 1; i < dim; i++)
3399  {
3400  size_t l = strlen(soap->type);
3401  (SOAP_SNPRINTF(soap->type + l, sizeof(soap->type) - l - 1, 20), t, size[i]);
3402  }
3403  }
3404  soap_strcat(soap->type, sizeof(soap->type), "]");
3405  return soap->type;
3406 }
3407 
3408 /******************************************************************************/
3409 
3410 SOAP_FMAC1
3411 char *
3412 SOAP_FMAC2
3413 soap_putoffsets(struct soap *soap, const int *offset, int dim)
3414 {
3415  int i;
3416  soap->arrayOffset[0] = '\0';
3417  if (soap->version == 1)
3418  {
3419  (SOAP_SNPRINTF(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, 20), "[%d", offset[0]);
3420  for (i = 1; i < dim; i++)
3421  {
3422  size_t l = strlen(soap->arrayOffset);
3423  (SOAP_SNPRINTF(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, 20), ",%d", offset[i]);
3424  }
3425  soap_strcat(soap->arrayOffset, sizeof(soap->arrayOffset), "]");
3426  }
3427  return soap->arrayOffset;
3428 }
3429 
3430 /******************************************************************************/
3431 
3432 SOAP_FMAC1
3433 size_t
3434 SOAP_FMAC2
3435 soap_size(const int *size, int dim)
3436 {
3437  int i;
3438  size_t n = 0;
3439  if (size[0] <= 0)
3440  return 0;
3441  n = (size_t)size[0];
3442  for (i = 1; i < dim; i++)
3443  {
3444  if (size[i] <= 0)
3445  return 0;
3446  n *= (size_t)size[i];
3447  }
3448  return (size_t)n;
3449 }
3450 
3451 /******************************************************************************/
3452 
3453 SOAP_FMAC1
3454 size_t
3455 SOAP_FMAC2
3456 soap_getsizes(const char *attr, int *size, int dim)
3457 {
3458  size_t i, k, n;
3459  if (!*attr)
3460  return 0;
3461  i = strlen(attr);
3462  n = 1;
3463  do
3464  {
3465  for (; i > 0; i--)
3466  if (attr[i - 1] == '[' || attr[i - 1] == ',' || attr[i - 1] == ' ')
3467  break;
3468  n *= k = (size_t)soap_strtoul(attr + i, NULL, 10);
3469  size[--dim] = (int)k;
3470  if (n > SOAP_MAXARRAYSIZE)
3471  return 0;
3472  } while (dim > 0 && --i > 0 && attr[i] != '[');
3473  return n;
3474 }
3475 
3476 /******************************************************************************/
3477 
3478 SOAP_FMAC1
3479 int
3480 SOAP_FMAC2
3481 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
3482 {
3483  int i, j = 0;
3484  if (offset)
3485  {
3486  for (i = 0; i < dim && attr && *attr; i++)
3487  {
3488  attr++;
3489  j *= size[i];
3490  j += offset[i] = (int)soap_strtol(attr, NULL, 10);
3491  attr = strchr(attr, ',');
3492  }
3493  }
3494  else
3495  {
3496  for (i = 0; i < dim && attr && *attr; i++)
3497  {
3498  attr++;
3499  j *= size[i];
3500  j += (int)soap_strtol(attr, NULL, 10);
3501  attr = strchr(attr, ',');
3502  }
3503  }
3504  return j;
3505 }
3506 
3507 /******************************************************************************/
3508 
3509 SOAP_FMAC1
3510 int
3511 SOAP_FMAC2
3512 soap_getposition(const char *attr, int *pos)
3513 {
3514  int i, n;
3515  if (!*attr)
3516  return -1;
3517  n = 0;
3518  i = 1;
3519  do
3520  {
3521  pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
3522  while (attr[i] && attr[i] != ',' && attr[i] != ']')
3523  i++;
3524  if (attr[i] == ',')
3525  i++;
3526  } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
3527  return n;
3528 }
3529 
3530 /******************************************************************************/
3531 
3532 SOAP_FMAC1
3533 struct soap_nlist *
3534 SOAP_FMAC2
3535 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
3536 {
3537  struct soap_nlist *np = NULL;
3538  struct Namespace *p;
3539  short i = -1;
3540  size_t n, k;
3541  n = strlen(id);
3542  k = strlen(ns) + 1;
3543  p = soap->local_namespaces;
3544  if (p)
3545  {
3546  for (i = 0; p->id; p++, i++)
3547  {
3548  if (p->ns && !strcmp(ns, p->ns))
3549  break;
3550  if (p->out)
3551  {
3552  if (!strcmp(ns, p->out))
3553  break;
3554  }
3555  else if (p->in)
3556  {
3557  if (!soap_tag_cmp(ns, p->in))
3558  {
3559  if (SOAP_MAXALLOCSIZE <= 0 || k <= SOAP_MAXALLOCSIZE)
3560  p->out = (char*)SOAP_MALLOC(soap, k);
3561  if (p->out)
3562  soap_strcpy(p->out, k, ns);
3563  break;
3564  }
3565  }
3566  }
3567  if (!p->id)
3568  i = -1;
3569  }
3570  if (i >= 0)
3571  k = 0;
3572  if (sizeof(struct soap_nlist) + n + k > n && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE))
3573  np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
3574  if (!np)
3575  {
3576  soap->error = SOAP_EOM;
3577  return NULL;
3578  }
3579  np->next = soap->nlist;
3580  soap->nlist = np;
3581  np->level = soap->level;
3582  np->index = i;
3583  soap_strcpy((char*)np->id, n + 1, id);
3584  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u,index=%hd) '%s'='%s'\n", soap->level, i, id, ns));
3585  if (i < 0)
3586  {
3587  np->ns = np->id + n + 1;
3588  soap_strcpy((char*)np->ns, k, ns);
3589  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
3590  }
3591  else
3592  {
3593  np->ns = NULL;
3594  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
3595  }
3596  return np;
3597 }
3598 
3599 /******************************************************************************/
3600 
3601 SOAP_FMAC1
3602 void
3603 SOAP_FMAC2
3605 {
3606  struct soap_nlist *np, *nq;
3607  for (np = soap->nlist; np && np->level >= soap->level; np = nq)
3608  {
3609  nq = np->next;
3610  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s' level=%u\n", soap->level, np->id, np->level));
3611  SOAP_FREE(soap, np);
3612  }
3613  soap->nlist = np;
3614 }
3615 
3616 /******************************************************************************/
3617 
3618 SOAP_FMAC1
3619 int
3620 SOAP_FMAC2
3621 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
3622 {
3623  struct soap_nlist *np = soap->nlist;
3624  const char *s;
3625  while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
3626  np = np->next;
3627  if (np)
3628  {
3629  if (!(soap->mode & SOAP_XML_IGNORENS) && (n2 > 0 || !np->ns || *np->ns))
3630  {
3631  if (np->index < 0
3632  || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))
3633  return SOAP_NAMESPACE;
3634  }
3635  return SOAP_OK;
3636  }
3637  if (n1 == 0)
3638  return n2 == 0 || (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;
3639  if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
3640  || (soap->mode & SOAP_XML_IGNORENS))
3641  return SOAP_OK;
3642  return soap->error = SOAP_SYNTAX_ERROR;
3643 }
3644 
3645 /******************************************************************************/
3646 
3647 SOAP_FMAC1
3648 const char*
3649 SOAP_FMAC2
3650 soap_current_namespace_tag(struct soap *soap, const char *tag)
3651 {
3652  struct soap_nlist *np;
3653  const char *s;
3654  if (!tag || !strncmp(tag, "xml", 3))
3655  return NULL;
3656  np = soap->nlist;
3657  s = strchr(tag, ':');
3658  if (!s)
3659  {
3660  while (np && *np->id) /* find default namespace, if present */
3661  np = np->next;
3662  }
3663  else
3664  {
3665  while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
3666  np = np->next;
3667  if (!np)
3669  }
3670  if (np)
3671  {
3672  if (np->index >= 0)
3673  return soap->namespaces[np->index].ns;
3674  if (np->ns)
3675  {
3676  s = np->ns;
3677  if (*s)
3678  return soap_strdup(soap, s);
3679  do
3680  np = np->next;
3681  while (np && *np->id); /* find if there is any other default namespace */
3682  if (np)
3683  return soap_strdup(soap, s);
3684  }
3685  }
3686  return NULL;
3687 }
3688 
3689 /******************************************************************************/
3690 
3691 SOAP_FMAC1
3692 const char*
3693 SOAP_FMAC2
3694 soap_current_namespace_att(struct soap *soap, const char *tag)
3695 {
3696  struct soap_nlist *np;
3697  const char *s;
3698  if (!tag || !strncmp(tag, "xml", 3))
3699  return NULL;
3700  s = strchr(tag, ':');
3701  if (!s)
3702  return NULL;
3703  np = soap->nlist;
3704  while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
3705  np = np->next;
3706  if (!np)
3708  if (np)
3709  {
3710  if (np->index >= 0)
3711  return soap->namespaces[np->index].ns;
3712  if (np->ns && *np->ns)
3713  return soap_strdup(soap, np->ns);
3714  }
3715  return NULL;
3716 }
3717 
3718 /******************************************************************************/
3719 
3720 SOAP_FMAC1
3721 int
3722 SOAP_FMAC2
3723 soap_tag_cmp(const char *s, const char *t)
3724 {
3725  const char *a = NULL;
3726  const char *b = NULL;
3727  for (;;)
3728  {
3729  int c1 = *s;
3730  int c2 = *t;
3731  if (!c1 || c1 == '"')
3732  break;
3733  if (c2 != '-')
3734  {
3735  if (c1 < c2)
3736  {
3737  if (c1 >= 'A' && c1 <= 'Z')
3738  c1 += 'a' - 'A';
3739  }
3740  else if (c1 > c2)
3741  {
3742  if (c2 >= 'A' && c2 <= 'Z')
3743  c2 += 'a' - 'A';
3744  }
3745  if (c2 == '*')
3746  {
3747  c2 = *++t;
3748  if (!c2)
3749  return 0;
3750  a = s;
3751  b = t;
3752  continue;
3753  }
3754  if (c1 != c2)
3755  {
3756  if (!a)
3757  return 1;
3758  s = ++a;
3759  t = b;
3760  continue;
3761  }
3762  }
3763  s++;
3764  t++;
3765  }
3766  if (*t == '*' && !t[1])
3767  return 0;
3768  return *t;
3769 }
3770 
3771 /******************************************************************************/
3772 
3773 SOAP_FMAC1
3774 int
3775 SOAP_FMAC2
3776 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
3777 {
3778  const char *s, *t;
3779  int err;
3780  if (!tag1 || !tag2 || !*tag2)
3781  return SOAP_OK;
3782  s = strchr(tag1, ':');
3783  t = strchr(tag2, ':');
3784  if (t)
3785  {
3786  if (s)
3787  {
3788  if (t[1] && SOAP_STRCMP(s + 1, t + 1))
3789  return SOAP_TAG_MISMATCH;
3790  if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS))
3791  {
3792  err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2);
3793  if (err)
3794  {
3795  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
3796  if (err == SOAP_NAMESPACE)
3797  return SOAP_TAG_MISMATCH;
3798  return err;
3799  }
3800  }
3801  }
3802  else if (!t[1])
3803  {
3804  if ((soap->mode & SOAP_XML_IGNORENS) || soap_match_namespace(soap, tag1, tag2, 0, t - tag2))
3805  return SOAP_TAG_MISMATCH;
3806  }
3807  else if (SOAP_STRCMP(tag1, t + 1))
3808  {
3809  return SOAP_TAG_MISMATCH;
3810  }
3811  else if (t != tag2)
3812  {
3813  err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);
3814  if (err)
3815  {
3816  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
3817  if (err == SOAP_NAMESPACE)
3818  return SOAP_TAG_MISMATCH;
3819  return err;
3820  }
3821  }
3822  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
3823  return SOAP_OK;
3824  }
3825  if (s)
3826  {
3827  if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */
3828  return SOAP_TAG_MISMATCH;
3829  }
3830  else if (SOAP_STRCMP(tag1, tag2)
3831 #ifndef WITH_NOEMPTYNAMESPACES
3832  || ((soap->mode & SOAP_XML_STRICT) && !(soap->mode & SOAP_XML_IGNORENS) && soap_match_namespace(soap, tag1, tag2, 0, 0)) /* strict checking: default namespace must be null namespace */
3833 #endif
3834  )
3835  {
3836  return SOAP_TAG_MISMATCH;
3837  }
3838  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
3839  return SOAP_OK;
3840 }
3841 
3842 /******************************************************************************/
3843 
3844 SOAP_FMAC1
3845 int
3846 SOAP_FMAC2
3847 soap_match_att(struct soap *soap, const char *tag1, const char *tag2)
3848 {
3849  const char *s, *t;
3850  int err;
3851  if (!tag1 || !tag2 || !*tag2)
3852  return SOAP_OK;
3853  s = strchr(tag1, ':');
3854  t = strchr(tag2, ':');
3855  if (t)
3856  {
3857  if (s)
3858  {
3859  if (t[1] && SOAP_STRCMP(s + 1, t + 1))
3860  return SOAP_TAG_MISMATCH;
3861  if (t != tag2 && !(soap->mode & SOAP_XML_IGNORENS))
3862  {
3863  err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2);
3864  if (err)
3865  {
3866  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts '%s' and '%s' match but namespaces differ\n", tag1, tag2));
3867  if (err == SOAP_NAMESPACE)
3868  return SOAP_TAG_MISMATCH;
3869  return err;
3870  }
3871  }
3872  }
3873  else if (!t[1] || t != tag2 || SOAP_STRCMP(tag1, t + 1))
3874  return SOAP_TAG_MISMATCH;
3875  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
3876  return SOAP_OK;
3877  }
3878  if (s)
3879  {
3880  if (!(soap->mode & SOAP_XML_IGNORENS) || SOAP_STRCMP(s + 1, tag2)) /* always fails (except when ignoring ns) */
3881  return SOAP_TAG_MISMATCH;
3882  }
3883  else if (SOAP_STRCMP(tag1, tag2))
3884  return SOAP_TAG_MISMATCH;
3885  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Atts match: '%s' '%s'\n", tag1, tag2));
3886  return SOAP_OK;
3887 }
3888 
3889 /******************************************************************************/
3890 
3891 SOAP_FMAC1
3892 int
3893 SOAP_FMAC2
3894 soap_match_array(struct soap *soap, const char *type)
3895 {
3896  if (type && *soap->arrayType)
3897  {
3898  if (soap->version == 1 || !strchr(type, '['))
3899  {
3901  && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
3902  && soap_match_tag(soap, soap->arrayType, "xsd:ur-type"))
3903  {
3904  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SOAP array type mismatch: '%s' '%s'\n", soap->arrayType, type));
3905  return SOAP_TAG_MISMATCH;
3906  }
3907  }
3908  }
3909  return SOAP_OK;
3910 }
3911 
3912 /******************************************************************************\
3913  *
3914  * SSL/TLS
3915  *
3916 \******************************************************************************/
3917 
3918 #ifdef WITH_OPENSSL
3919 SOAP_FMAC1
3920 int
3921 SOAP_FMAC2
3922 soap_rand()
3923 {
3924  int r;
3925  if (!soap_ssl_init_done)
3926  soap_ssl_init();
3927 #if OPENSSL_VERSION_NUMBER < 0x10100000L
3928  RAND_pseudo_bytes((unsigned char*)&r, sizeof(int));
3929 #else
3930  RAND_bytes((unsigned char*)&r, sizeof(int));
3931 #endif
3932  return r;
3933 }
3934 #endif
3935 
3936 /******************************************************************************/
3937 
3938 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
3939 SOAP_FMAC1
3940 int
3941 SOAP_FMAC2
3942 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3943 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
3944 #else
3945 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
3946 #endif
3947 {
3948  int err;
3949  soap->keyfile = keyfile;
3950 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3951  soap->keyid = keyid; /* vxWorks compatible */
3952 #endif
3953  soap->password = password;
3954  soap->cafile = cafile;
3955  soap->capath = capath;
3956 #ifdef WITH_OPENSSL
3957  soap->dhfile = dhfile;
3958  soap->randfile = randfile;
3959  if (!soap->fsslverify)
3960  soap->fsslverify = ssl_verify_callback;
3961 #endif
3962  soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
3963 #ifdef WITH_GNUTLS
3964  (void)randfile; (void)sid;
3965  if (dhfile)
3966  {
3967  char *s;
3968  int n = (int)soap_strtoul(dhfile, &s, 10);
3969  if (!soap->dh_params)
3970  gnutls_dh_params_init(&soap->dh_params);
3971  /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3972  if (n >= 512 && s && *s == '\0')
3973  gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n);
3974  else
3975  {
3976  unsigned int dparams_len;
3977  unsigned char dparams_buf[1024];
3978  FILE *fd = fopen(dhfile, "r");
3979  if (!fd)
3980  return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
3981  dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd);
3982  fclose(fd);
3983  gnutls_datum_t dparams = {
3984  dparams_buf, dparams_len };
3985  if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM))
3986  return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
3987  }
3988  }
3989  else
3990  {
3991 #if GNUTLS_VERSION_NUMBER < 0x030300
3992  if (!soap->rsa_params)
3993  gnutls_rsa_params_init(&soap->rsa_params);
3994  gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS);
3995 #endif
3996  }
3997  if (soap->session)
3998  {
3999  gnutls_deinit(soap->session);
4000  soap->session = NULL;
4001  }
4002  if (soap->xcred)
4003  {
4004  gnutls_certificate_free_credentials(soap->xcred);
4005  soap->xcred = NULL;
4006  }
4007 #endif
4008 #ifdef WITH_SYSTEMSSL
4009  (void)randfile; (void)sid;
4010  if (soap->ctx)
4011  gsk_environment_close(&soap->ctx);
4012 #endif
4013  err = soap->fsslauth(soap);
4014 #ifdef WITH_OPENSSL
4015  if (!err)
4016  {
4017  if (sid)
4018  SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
4019  else
4020  SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
4021  }
4022 #endif
4023  return err;
4024 }
4025 #endif
4026 
4027 /******************************************************************************/
4028 
4029 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
4030 SOAP_FMAC1
4031 int
4032 SOAP_FMAC2
4033 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
4034 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *randfile)
4035 #else
4036 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile)
4037 #endif
4038 {
4039  soap->keyfile = keyfile;
4040 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
4041  soap->keyid = keyid; /* vxWorks compatible */
4042 #endif
4043  soap->password = password;
4044  soap->cafile = cafile;
4045  soap->capath = capath;
4046  soap->ssl_flags = SOAP_SSL_CLIENT | flags;
4047 #ifdef WITH_OPENSSL
4048  soap->dhfile = NULL;
4049  soap->randfile = randfile;
4050  if (!soap->fsslverify)
4051  soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
4052 #endif
4053 #ifdef WITH_GNUTLS
4054  (void)randfile;
4055  if (soap->session)
4056  {
4057  gnutls_deinit(soap->session);
4058  soap->session = NULL;
4059  }
4060  if (soap->xcred)
4061  {
4062  gnutls_certificate_free_credentials(soap->xcred);
4063  soap->xcred = NULL;
4064  }
4065 #endif
4066 #ifdef WITH_SYSTEMSSL
4067  (void)randfile;
4068  if (soap->ctx)
4069  gsk_environment_close(&soap->ctx);
4070 #endif
4071  return soap->fsslauth(soap);
4072 }
4073 #endif
4074 
4075 /******************************************************************************/
4076 
4077 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
4078 SOAP_FMAC1
4079 int
4080 SOAP_FMAC2
4081 soap_ssl_crl(struct soap *soap, const char *crlfile)
4082 {
4083 #ifdef WITH_OPENSSL
4084  if (crlfile && soap->ctx)
4085  {
4086 #if OPENSSL_VERSION_NUMBER > 0x00907000L
4087  X509_STORE *store = SSL_CTX_get_cert_store(soap->ctx);
4088  if (*crlfile)
4089  {
4090  int ret;
4091  X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
4092  if (!lookup)
4093  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't create X509_LOOKUP object", SOAP_SSL_ERROR);
4094  ret = X509_load_crl_file(lookup, crlfile, X509_FILETYPE_PEM);
4095  if (ret <= 0)
4096  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR);
4097  }
4098  X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
4099 #endif
4100  }
4101  else
4102  soap->crlfile = crlfile; /* activate later when store is available */
4103 #endif
4104 #ifdef WITH_GNUTLS
4105  if (crlfile && soap->xcred)
4106  {
4107  if (*crlfile)
4108  if (gnutls_certificate_set_x509_crl_file(soap->xcred, crlfile, GNUTLS_X509_FMT_PEM) < 0)
4109  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL PEM file", SOAP_SSL_ERROR);
4110  }
4111  else
4112  {
4113  soap->crlfile = crlfile; /* activate later when xcred is available */
4114  }
4115 #endif
4116  return SOAP_OK;
4117 }
4118 #endif
4119 
4120 /******************************************************************************/
4121 
4122 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
4123 SOAP_FMAC1
4124 void
4125 SOAP_FMAC2
4126 soap_ssl_init()
4127 {
4128  /* Note: for multi-threaded applications, the main program should call soap_ssl_init() before any threads are started */
4129  if (!soap_ssl_init_done)
4130  {
4131  soap_ssl_init_done = 1;
4132 #ifdef WITH_OPENSSL
4133 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4134  SSL_library_init();
4135  OpenSSL_add_all_algorithms(); /* we keep ciphers and digests for the program's lifetime */
4136 #ifndef WITH_LEAN
4137  SSL_load_error_strings();
4138 #endif
4139 #endif
4140 #if !defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__)
4141  if (!RAND_load_file("/dev/urandom", 1024))
4142 #else
4143  if (1)
4144 #endif
4145  {
4146  /* if /dev/urandom does not exist we need to do at least some pertubations to seed the OpenSSL PRNG */
4147  char buf[1024];
4148  RAND_seed(buf, sizeof(buf));
4149 #ifdef HAVE_RANDOM
4150  srandom((unsigned long)time(NULL));
4151 #else
4152  srand((unsigned int)time(NULL));
4153 #endif
4154  do
4155  {
4156 #ifdef HAVE_RANDOM
4157  long r = random(); /* we actually do no use random() anywhere, except to further seed the OpenSSL PRNG */
4158  RAND_seed(&r, sizeof(long));
4159 #else
4160  int r = rand(); /* we actually do no use rand() anywhere, except when random() is not available and to further seed the OpenSSL PRNG */
4161  RAND_seed(&r, sizeof(int));
4162 #endif
4163  } while (!RAND_status());
4164  }
4165 #endif
4166 #ifdef WITH_GNUTLS
4167 # if GNUTLS_VERSION_NUMBER < 0x020b00
4168 # if defined(HAVE_PTHREAD_H)
4169  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
4170 # elif defined(HAVE_PTH_H)
4171  gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
4172 # endif
4173  gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
4174  gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
4175  gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */
4176 # endif
4177 # if GNUTLS_VERSION_NUMBER < 0x030300
4178  gnutls_global_init();
4179 # endif
4180 #endif
4181  }
4182 }
4183 #endif
4184 
4185 /******************************************************************************/
4186 
4187 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
4188 SOAP_FMAC1
4189 void
4190 SOAP_FMAC2
4192 {
4193  /* Call this first to bypass SSL init is SSL is already initialized elsewhere */
4194  soap_ssl_init_done = 1;
4195 }
4196 #endif
4197 
4198 /******************************************************************************/
4199 
4200 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
4201 SOAP_FMAC1
4202 const char *
4203 SOAP_FMAC2
4204 soap_ssl_error(struct soap *soap, int ret, int err)
4205 {
4206 #ifdef WITH_OPENSSL
4207  const char *msg = soap_code_str(h_ssl_error_codes, err);
4208  if (!msg)
4209  return ERR_error_string(err, soap->msgbuf);
4210  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(msg) + 1), "%s\n", msg);
4211  if (ERR_peek_error())
4212  {
4213  unsigned long r;
4214  while ((r = ERR_get_error()))
4215  {
4216  size_t l = strlen(soap->msgbuf);
4217  ERR_error_string_n(r, soap->msgbuf + l, sizeof(soap->msgbuf) - l);
4218  l = strlen(soap->msgbuf);
4219  if (l + 1 < sizeof(soap->msgbuf))
4220  {
4221  soap->msgbuf[l++] = '\n';
4222  soap->msgbuf[l] = '\0';
4223  }
4224  if (ERR_GET_REASON(r) == SSL_R_CERTIFICATE_VERIFY_FAILED && l < sizeof(soap->msgbuf))
4225  {
4226  const char *s = X509_verify_cert_error_string(SSL_get_verify_result(soap->ssl));
4227  (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s)), "%s", s);
4228  }
4229  }
4230  }
4231  else
4232  {
4233  size_t l = strlen(soap->msgbuf);
4234  switch (ret)
4235  {
4236  case 0:
4237  soap_strcpy(soap->msgbuf + l, sizeof(soap->msgbuf) - l, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information.");
4238  break;
4239  case -1:
4240  {
4241  const char *s = strerror(soap_errno);
4242  (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, strlen(s) + 42), "Error observed by underlying SSL/TLS BIO: %s", s);
4243  }
4244  break;
4245  }
4246  }
4247  ERR_clear_error();
4248  return soap->msgbuf;
4249 #endif
4250 #ifdef WITH_GNUTLS
4251  (void)soap;
4252  (void)err;
4253  return gnutls_strerror(ret);
4254 #endif
4255 }
4256 #endif
4257 
4258 /******************************************************************************/
4259 
4260 #ifdef WITH_SYSTEMSSL
4261 static int
4262 ssl_recv(int sk, void *s, int n, char *user)
4263 {
4264  (void)user;
4265  return recv(sk, s, n, 0);
4266 }
4267 #endif
4268 
4269 /******************************************************************************/
4270 
4271 #ifdef WITH_SYSTEMSSL
4272 static int
4273 ssl_send(int sk, void *s, int n, char *user)
4274 {
4275  (void)user;
4276  return send(sk, s, n, 0);
4277 }
4278 #endif
4279 
4280 /******************************************************************************/
4281 
4282 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
4283 static int
4284 ssl_auth_init(struct soap *soap)
4285 {
4286 #ifdef WITH_OPENSSL
4287 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
4288  int minv = 0, maxv = 0;
4289 #endif
4290  long flags = SSL_OP_ALL;
4291  int mode;
4292 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
4293  EVP_PKEY* pkey; /* vxWorks compatible */
4294 #endif
4295  if (!soap_ssl_init_done)
4296  soap_ssl_init();
4297  ERR_clear_error();
4298  if (!soap->ctx)
4299  {
4300 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
4301  /* TLS_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. */
4302  soap->ctx = SSL_CTX_new(TLS_method());
4303 #else
4304  /* SSLv23_method: a TLS/SSL connection established may understand the SSLv3, TLSv1, TLSv1.1 and TLSv1.2 protocols. */
4305  soap->ctx = SSL_CTX_new(SSLv23_method());
4306 #endif
4307  if (!soap->ctx)
4308  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR);
4309  /* The following alters the behavior of SSL read/write: */
4310 #if 0
4311  SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
4312 #endif
4313  }
4314  if (soap->randfile)
4315  {
4316  if (!RAND_load_file(soap->randfile, -1))
4317  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR);
4318  }
4319  if (soap->cafile || soap->capath)
4320  {
4321  if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
4322  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
4324  SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
4325  }
4327  {
4328  if (!SSL_CTX_set_default_verify_paths(soap->ctx))
4329  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA PEM file and/or directory", SOAP_SSL_ERROR);
4330  }
4331  if (soap->crlfile)
4332  {
4333  if (soap_ssl_crl(soap, soap->crlfile))
4334  return soap->error;
4335  }
4336 /* This code assumes a typical scenario with key and cert in one PEM file, see alternative code below */
4337 #if 1
4338  if (soap->keyfile)
4339  {
4340  if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
4341  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR);
4342  if (soap->password)
4343  {
4344  SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
4345  SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
4346  }
4347 #ifndef WM_SECURE_KEY_STORAGE
4348  if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
4349  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
4350 #endif
4351  }
4352 #else
4353 /* Suggested alternative approach to check the key file for cert only when cafile==NULL */
4354  if (soap->password)
4355  {
4356  SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
4357  SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
4358  }
4359  if (!soap->cafile)
4360  {
4361  if (soap->keyfile)
4362  {
4363  if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
4364  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't find or read certificate in private key PEM file", SOAP_SSL_ERROR);
4365  if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
4366  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
4367  }
4368  }
4369  else /* use cafile for (server) cert and keyfile for (server) key */
4370  {
4371  if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
4372  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
4373  if (soap->keyfile)
4374  if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
4375  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
4376  }
4377 #endif
4378 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
4379  /* vxWorks compatible */
4380  pkey = ipcom_key_db_pkey_get(soap->keyid);
4381  if (!pkey)
4382  return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR);
4383  if (!SSL_CTX_use_PrivateKey(soap->ctx, pkey))
4384  return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR);
4385 #endif
4386  if ((soap->ssl_flags & SOAP_SSL_RSA))
4387  {
4388 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
4389  if (SSL_CTX_need_tmp_RSA(soap->ctx))
4390  {
4391  unsigned long e = RSA_F4;
4392  BIGNUM *bne = BN_new();
4393  RSA *rsa = RSA_new();
4394  if (!bne || !rsa || !BN_set_word(bne, e) || !RSA_generate_key_ex(rsa, SOAP_SSL_RSA_BITS, bne, NULL) || !SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
4395  {
4396  if (bne)
4397  BN_free(bne);
4398  if (rsa)
4399  RSA_free(rsa);
4400  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR);
4401  }
4402  BN_free(bne);
4403  RSA_free(rsa);
4404  }
4405 #else
4406  RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL);
4407  if (!rsa || !SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
4408  {
4409  if (rsa)
4410  RSA_free(rsa);
4411  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate RSA key", SOAP_SSL_ERROR);
4412  }
4413  RSA_free(rsa);
4414 #endif
4415  }
4416  else if (soap->dhfile)
4417  {
4418  DH *dh = NULL;
4419  char *s;
4420  int n = (int)soap_strtoul(soap->dhfile, &s, 10);
4421  /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
4422  if (n >= 512 && s && *s == '\0')
4423  {
4424 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
4425  dh = DH_new();
4426  if (!DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL))
4427  {
4428  DH_free(dh);
4429  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't generate DH parameters", SOAP_SSL_ERROR);
4430  }
4431 #elif defined(VXWORKS)
4432  dh = DH_new();
4433  DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL);
4434 #else
4435  dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
4436 #endif
4437  }
4438  else
4439  {
4440  BIO *bio;
4441  bio = BIO_new_file(soap->dhfile, "r");
4442  if (!bio)
4443  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH PEM file", SOAP_SSL_ERROR);
4444  dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
4445  BIO_free(bio);
4446  }
4447  if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
4448  {
4449  if (dh)
4450  DH_free(dh);
4451  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR);
4452  }
4453  DH_free(dh);
4454  }
4455  /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
4456  if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == 0)
4458 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
4459  if ((soap->ssl_flags & SOAP_SSLv3))
4460  minv = SSL3_VERSION;
4461  else if ((soap->ssl_flags & SOAP_TLSv1_0))
4462  minv = TLS1_VERSION;
4463  else if ((soap->ssl_flags & SOAP_TLSv1_1))
4464  minv = TLS1_1_VERSION;
4465  else if ((soap->ssl_flags & SOAP_TLSv1_2))
4466  minv = TLS1_2_VERSION;
4467  else if ((soap->ssl_flags & SOAP_TLSv1_3))
4468  minv = TLS1_3_VERSION;
4469  if ((soap->ssl_flags & SOAP_TLSv1_3) && OpenSSL_version_num() >= 0x10101000L)
4470  maxv = TLS1_3_VERSION;
4471  else if ((soap->ssl_flags & SOAP_TLSv1_2))
4472  maxv = TLS1_2_VERSION;
4473  else if ((soap->ssl_flags & SOAP_TLSv1_1))
4474  maxv = TLS1_1_VERSION;
4475  else if ((soap->ssl_flags & SOAP_TLSv1_0))
4476  maxv = TLS1_VERSION;
4477  else
4478  maxv = SSL3_VERSION;
4479  if (!SSL_CTX_set_min_proto_version(soap->ctx, minv)
4480  || !SSL_CTX_set_max_proto_version(soap->ctx, maxv))
4481  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol version", SOAP_SSL_ERROR);
4482 #else
4483  /* disable SSL v2 by default and enable specific protos */
4484  flags = SSL_OP_NO_SSLv2;
4485  if (!(soap->ssl_flags & SOAP_SSLv3))
4486  flags |= SSL_OP_NO_SSLv3;
4487 #if OPENSSL_VERSION_NUMBER >= 0x10001000L
4488  if (!(soap->ssl_flags & SOAP_TLSv1_0))
4489  flags |= SSL_OP_NO_TLSv1;
4490  if (!(soap->ssl_flags & SOAP_TLSv1_1))
4491  flags |= SSL_OP_NO_TLSv1_1;
4492  if (!(soap->ssl_flags & SOAP_TLSv1_2))
4493  flags |= SSL_OP_NO_TLSv1_2;
4494 #endif
4495 #endif
4496 #ifdef SSL_OP_NO_TICKET
4497  /* TLS extension is enabled by default in OPENSSL v0.9.8k disable it by */
4498  flags |= SSL_OP_NO_TICKET;
4499 #endif
4500  SSL_CTX_set_options(soap->ctx, flags);
4502  mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
4504  mode = SSL_VERIFY_PEER;
4505  else
4506  mode = SSL_VERIFY_NONE;
4507  SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
4508 #if OPENSSL_VERSION_NUMBER < 0x00905100L
4509  SSL_CTX_set_verify_depth(soap->ctx, 1);
4510 #else
4511  SSL_CTX_set_verify_depth(soap->ctx, 9);
4512 #endif
4513 #endif
4514 #ifdef WITH_GNUTLS
4515  int ret;
4516  char priority[80];
4517  soap_strcpy(priority, sizeof(priority), "PERFORMANCE");
4518  if (!soap_ssl_init_done)
4519  soap_ssl_init();
4520  if (!soap->xcred)
4521  {
4522  if (gnutls_certificate_allocate_credentials(&soap->xcred) != GNUTLS_E_SUCCESS)
4523  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't allocate credentials or trust", SOAP_SSL_ERROR);
4524 #if GNUTLS_VERSION_NUMBER >= 0x030300
4525  gnutls_certificate_set_x509_system_trust(soap->xcred);
4526 #endif
4527  if (soap->cafile)
4528  {
4529  if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0)
4530  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA PEM file", SOAP_SSL_ERROR);
4531  }
4532  if (soap->crlfile)
4533  {
4534  if (soap_ssl_crl(soap, soap->crlfile))
4535  return soap->error;
4536  }
4537  if (soap->keyfile)
4538  {
4539  if (gnutls_certificate_set_x509_key_file2(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM, soap->password, GNUTLS_PKCS_PKCS12_3DES | GNUTLS_PKCS_PKCS12_ARCFOUR | GNUTLS_PKCS_PKCS12_RC2_40 | GNUTLS_PKCS_PBES2_AES_128 | GNUTLS_PKCS_PBES2_AES_192 | GNUTLS_PKCS_PBES2_AES_256 | GNUTLS_PKCS_PBES2_DES) < 0) /* Assumes that key and cert(s) are concatenated in the keyfile and the key is encrypted with one of these algorithms */
4540  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read private key PEM file", SOAP_SSL_ERROR);
4541  }
4542  }
4543  if ((soap->ssl_flags & SOAP_SSL_CLIENT))
4544  {
4545  gnutls_init(&soap->session, GNUTLS_CLIENT);
4546  if (soap->cafile || soap->crlfile || soap->keyfile)
4547  {
4548  ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL);
4549  if (ret != GNUTLS_E_SUCCESS)
4550  return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR);
4551  gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
4552  }
4553  else
4554  {
4555  if (!soap->acred)
4556  gnutls_anon_allocate_client_credentials(&soap->acred);
4557  ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL);
4558  if (ret != GNUTLS_E_SUCCESS)
4559  return soap_set_receiver_error(soap, soap_ssl_error(soap, ret, 0), "SSL/TLS set priority error", SOAP_SSL_ERROR);
4560  gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred);
4561  }
4562  }
4563  else if (!soap->keyfile)
4564  {
4565  return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR);
4566  }
4567  else
4568  {
4569 #if GNUTLS_VERSION_NUMBER < 0x030300
4570  int protocol_priority[] = { 0, 0, 0, 0, 0 };
4571  int *protocol = protocol_priority;
4572  if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params)
4573  gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params);
4574 #endif
4575  if (!(soap->ssl_flags & SOAP_SSL_RSA) && soap->dh_params)
4576  gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params);
4577  if (!soap->cache)
4578  gnutls_priority_init(&soap->cache, "NORMAL", NULL);
4579  gnutls_init(&soap->session, GNUTLS_SERVER);
4580  gnutls_priority_set(soap->session, soap->cache);
4581  gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
4583  gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST);
4584  gnutls_session_enable_compatibility_mode(soap->session);
4585  /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
4586  if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == 0)
4588 #if GNUTLS_VERSION_NUMBER < 0x030300
4589  if ((soap->ssl_flags & SOAP_SSLv3))
4590  *protocol++ = GNUTLS_SSL3;
4591  if ((soap->ssl_flags & SOAP_TLSv1_0))
4592  *protocol++ = GNUTLS_TLS1_0;
4593  if ((soap->ssl_flags & SOAP_TLSv1_1))
4594  *protocol++ = GNUTLS_TLS1_1;
4595  if ((soap->ssl_flags & SOAP_TLSv1_2))
4596  *protocol++ = GNUTLS_TLS1_2;
4597  if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS)
4598  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol", SOAP_SSL_ERROR);
4599 #else
4600  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "NORMAL:+VERS-ALL");
4601  if (!(soap->ssl_flags & SOAP_TLSv1_0))
4602  soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.0");
4603  if (!(soap->ssl_flags & SOAP_TLSv1_1))
4604  soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.1");
4605  if (!(soap->ssl_flags & SOAP_TLSv1_2))
4606  soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), ":-VERS-TLS1.2");
4607  if (gnutls_priority_set_direct(soap->session, soap->tmpbuf, NULL) != GNUTLS_E_SUCCESS)
4608  return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set protocol priority", SOAP_SSL_ERROR);
4609 #endif
4610  }
4611 #endif
4612 #ifdef WITH_SYSTEMSSL
4613  if (!soap->ctx)
4614  {
4615  int err;
4616  err = gsk_environment_open(&soap->ctx);
4617  if (err == GSK_OK)
4618  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV2, GSK_PROTOCOL_SSLV2_OFF);
4619  /* enable all TSLv1 protocols and disable SSLv3 by default if no SSL/TLS flags are set */
4620  if ((soap->ssl_flags & SOAP_SSLv3_TLSv1) == 0)
4622  if (err == GSK_OK)
4623  {
4624  if ((soap->ssl_flags & SOAP_SSLv3))
4625  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_ON);
4626  else
4627  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_SSLV3, GSK_PROTOCOL_SSLV3_OFF);
4628  }
4629  if (err == GSK_OK)
4630  {
4631  if ((soap->ssl_flags & SOAP_TLSv1_0))
4632  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_ON);
4633  else
4634  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_OFF);
4635  }
4636  if (err == GSK_OK)
4637  {
4638  if ((soap->ssl_flags & SOAP_TLSv1_1))
4639  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_ON);
4640  else
4641  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_1_OFF);
4642  }
4643  if (err == GSK_OK)
4644  {
4645  if ((soap->ssl_flags & SOAP_TLSv1_2))
4646  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_ON);
4647  else
4648  err = gsk_attribute_set_enum(soap->ctx, GSK_PROTOCOL_TLSV1, GSK_PROTOCOL_TLSV1_2_OFF);
4649  }
4650  if (err == GSK_OK)
4651  err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_FILE, soap->keyfile, 0); /* keyfile is a keyring .kdb file */
4652  if (err == GSK_OK)
4653  err = gsk_attribute_set_buffer(soap->ctx, GSK_KEYRING_PW, soap->password, 0); /* locked by password */
4654  if (err == GSK_OK)
4655  err = gsk_environment_init(soap->ctx);
4656  if (err != GSK_OK)
4657  return soap_set_receiver_error(soap, gsk_strerror(err), "SYSTEM SSL error in ssl_auth_init()", SOAP_SSL_ERROR);
4658  }
4659 #endif
4660  return SOAP_OK;
4661 }
4662 #endif
4663 
4664 /******************************************************************************/
4665 
4666 #ifdef WITH_OPENSSL
4667 static int
4668 ssl_password(char *buf, int num, int rwflag, void *userdata)
4669 {
4670  (void)rwflag;
4671  if (!buf || !userdata)
4672  return 0;
4673  soap_strcpy(buf, (size_t)num, (char*)userdata);
4674  return (int)strlen(buf);
4675 }
4676 #endif
4677 
4678 /******************************************************************************/
4679 
4680 #ifdef WITH_OPENSSL
4681 static int
4682 ssl_verify_callback(int ok, X509_STORE_CTX *store)
4683 {
4684  (void)store;
4685 #ifdef SOAP_DEBUG
4686  if (!ok)
4687  {
4688  char buf[1024];
4689  int err = X509_STORE_CTX_get_error(store);
4690  X509 *cert = X509_STORE_CTX_get_current_cert(store);
4691  fprintf(stderr, "\nDEBUG mode TLS/SSL warnings:\nSSL verify error %d or warning with certificate at depth %d: %s\n", err, X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(err));
4692  X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf)-1);
4693  fprintf(stderr, " certificate issuer: %s\n", buf);
4694  X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)-1);
4695  fprintf(stderr, " certificate subject: %s\n", buf);
4696  /* accept self-signed certificates and certificates out of date */
4697  switch (err)
4698  {
4699  case X509_V_ERR_CERT_NOT_YET_VALID:
4700  case X509_V_ERR_CERT_HAS_EXPIRED:
4701  case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
4702  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
4703  case X509_V_ERR_UNABLE_TO_GET_CRL:
4704  case X509_V_ERR_CRL_NOT_YET_VALID:
4705  case X509_V_ERR_CRL_HAS_EXPIRED:
4706  X509_STORE_CTX_set_error(store, X509_V_OK);
4707  ok = 1;
4708  fprintf(stderr, "Initialize soap_ssl_client_context with SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE to allow this verification error to pass without DEBUG mode enabled\n");
4709  }
4710  }
4711 #endif
4712  /* Note: return 1 to try to continue, but unsafe progress will be terminated by OpenSSL */
4713  return ok;
4714 }
4715 #endif
4716 
4717 /******************************************************************************/
4718 
4719 #ifdef WITH_OPENSSL
4720 static int
4721 ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
4722 {
4723  ok = ssl_verify_callback(ok, store);
4724  if (!ok)
4725  {
4726  /* accept self signed certificates, expired certificates, and certficiates w/o CRL */
4727  switch (X509_STORE_CTX_get_error(store))
4728  {
4729  case X509_V_ERR_CERT_NOT_YET_VALID:
4730  case X509_V_ERR_CERT_HAS_EXPIRED:
4731  case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
4732  case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
4733  case X509_V_ERR_UNABLE_TO_GET_CRL:
4734  case X509_V_ERR_CRL_NOT_YET_VALID:
4735  case X509_V_ERR_CRL_HAS_EXPIRED:
4736  X509_STORE_CTX_set_error(store, X509_V_OK);
4737  ok = 1;
4738  }
4739  }
4740  /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
4741  return ok;
4742 }
4743 #endif
4744 
4745 /******************************************************************************/
4746 
4747 #ifdef WITH_GNUTLS
4748 static const char *
4749 ssl_verify(struct soap *soap, const char *host)
4750 {
4751  unsigned int status;
4752  const char *err = NULL;
4753  int r = gnutls_certificate_verify_peers2(soap->session, &status);
4754  if (r < 0)
4755  err = "Certificate verify error";
4756  else if ((status & GNUTLS_CERT_INVALID))
4757  err = "The certificate is not trusted";
4758  else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND))
4759  err = "The certificate hasn't got a known issuer";
4760  else if ((status & GNUTLS_CERT_REVOKED))
4761  err = "The certificate has been revoked";
4762  else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509)
4763  {
4764  gnutls_x509_crt_t cert;
4765  const gnutls_datum_t *cert_list;
4766  unsigned int cert_list_size;
4767  if (gnutls_x509_crt_init(&cert) < 0)
4768  err = "Could not get X509 certificates";
4769  else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL)
4770  err = "Could not get X509 certificates";
4771  else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
4772  err = "Error parsing X509 certificate";
4773  else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
4774  err = "The certificate has expired";
4775  else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL))
4776  err = "The certificate is not yet activated";
4777  else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
4778  {
4779  if (!gnutls_x509_crt_check_hostname(cert, host))
4780  err = "Certificate host name mismatch";
4781  }
4782  gnutls_x509_crt_deinit(cert);
4783  }
4784  return err;
4785 }
4786 #endif
4787 
4788 /******************************************************************************/
4789 
4790 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
4791 #ifndef WITH_NOIO
4792 SOAP_FMAC1
4793 int
4794 SOAP_FMAC2
4795 soap_ssl_accept(struct soap *soap)
4796 {
4797  SOAP_SOCKET sk = soap->socket;
4798 #ifdef WITH_OPENSSL
4799  BIO *bio;
4800  int err = SSL_ERROR_NONE;
4801  int retries, r, s;
4802  ERR_clear_error();
4803  if (!soap_valid_socket(sk))
4804  return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
4806  if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
4807  return soap_closesock(soap);
4808  if (!soap->ssl)
4809  {
4810  soap->ssl = SSL_new(soap->ctx);
4811  if (!soap->ssl)
4812  {
4814  return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
4815  }
4816  }
4817  else
4818  {
4819  SSL_clear(soap->ssl);
4820  }
4821  bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
4822  SSL_set_bio(soap->ssl, bio, bio);
4823  /* Default timeout: 10 sec retries, 100 times 0.1 sec */
4824  retries = 100;
4826  {
4828  if (t > 0)
4829  retries = 10 * t;
4830  else if (t > -100000)
4831  retries = 1;
4832  else
4833  retries = t/-100000;
4834  }
4835  SOAP_SOCKNONBLOCK(sk)
4836  while ((r = SSL_accept(soap->ssl)) <= 0)
4837  {
4838  err = SSL_get_error(soap->ssl, r);
4839  if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
4840  {
4841  if (err == SSL_ERROR_WANT_READ)
4843  else
4845  if (s < 0)
4846  break;
4847  }
4848  else
4849  {
4851  break;
4852  }
4853  if (retries-- <= 0)
4854  break;
4855  }
4856  if (!soap->recv_timeout && !soap->send_timeout)
4857  SOAP_SOCKBLOCK(sk)
4858  if (r <= 0)
4859  {
4860  soap_set_receiver_error(soap, soap_ssl_error(soap, r, err), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
4861  return soap_closesock(soap);
4862  }
4864  {
4865  X509 *peer;
4866  int err;
4867  if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
4868  {
4870  return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR);
4871  }
4872  peer = SSL_get_peer_certificate(soap->ssl);
4873  if (!peer)
4874  {
4876  return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
4877  }
4878  X509_free(peer);
4879  }
4880 #endif
4881 #ifdef WITH_GNUTLS
4882  int retries, r, s;
4883  if (!soap_valid_socket(sk))
4884  return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
4886  if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
4887  return soap_closesock(soap);
4888  gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
4889  /* default timeout: 10 sec retries, 100 times 0.1 sec */
4890  retries = 100;
4892  {
4894  if (t > 0)
4895  retries = 10 * t;
4896  else if (t > -100000)
4897  retries = 1;
4898  else
4899  retries = t/-100000;
4900  }
4901  SOAP_SOCKNONBLOCK(sk)
4902  while ((r = gnutls_handshake(soap->session)))
4903  {
4904  /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
4905  if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
4906  {
4907  if (!gnutls_record_get_direction(soap->session))
4909  else
4911  if (s < 0)
4912  break;
4913  }
4914  else
4915  {
4917  break;
4918  }
4919  if (retries-- <= 0)
4920  break;
4921  }
4922  if (!soap->recv_timeout && !soap->send_timeout)
4923  SOAP_SOCKBLOCK(sk)
4924  if (r)
4925  {
4926  soap_set_receiver_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
4927  return soap_closesock(soap);
4928  }
4930  {
4931  const char *err = ssl_verify(soap, NULL);
4932  if (err)
4933  {
4935  return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
4936  }
4937  }
4938 #endif
4939 #ifdef WITH_SYSTEMSSL
4940  gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL };
4941  int retries, r, s;
4942  if (!soap_valid_socket(sk))
4943  return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
4945  /* default timeout: 10 sec retries, 100 times 0.1 sec */
4946  retries = 100;
4948  {
4950  if (t > 0)
4951  retries = 10 * t;
4952  else if (t > -100000)
4953  retries = 1;
4954  else
4955  retries = t/-100000;
4956  }
4957  SOAP_SOCKNONBLOCK(sk)
4958  r = gsk_secure_socket_open(soap->ctx, &soap->ssl);
4959  if (r == GSK_OK)
4960  r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk);
4961  if (r == GSK_OK)
4962  r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0);
4963  if (r == GSK_OK)
4964  r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_SERVER_SESSION);
4965  if (r == GSK_OK)
4966  r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0);
4967  if (r == GSK_OK)
4968  r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4);
4969  if (r == GSK_OK)
4970  r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io);
4971  if (r != GSK_OK)
4972  return soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in soap_ssl_accept()", SOAP_SSL_ERROR);
4973  while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK)
4974  {
4975  if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE)
4976  {
4977  if (r == GSK_WOULD_BLOCK_READ)
4979  else
4981  if (s < 0)
4982  break;
4983  }
4984  else
4985  {
4987  break;
4988  }
4989  if (retries-- <= 0)
4990  break;
4991  }
4992  if (!soap->recv_timeout && !soap->send_timeout)
4993  SOAP_SOCKBLOCK(sk)
4994  if (r != GSK_OK)
4995  {
4996  soap_set_receiver_error(soap, gsk_strerror(r), "gsk_secure_socket_init() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
4997  return soap_closesock(soap);
4998  }
4999 #endif
5000  soap->imode |= SOAP_ENC_SSL;
5001  soap->omode |= SOAP_ENC_SSL;
5002  return SOAP_OK;
5003 }
5004 #endif
5005 #endif
5006 
5007 /******************************************************************************\
5008  *
5009  * TCP/UDP [SSL/TLS] IPv4 and IPv6
5010  *
5011 \******************************************************************************/
5012 
5013 #ifndef WITH_NOIO
5014 static int
5016 {
5017  soap->errmode = 1;
5018 #ifdef WIN32
5019  if (tcp_done)
5020  return 0;
5021  else
5022  {
5023  WSADATA w;
5024  if (WSAStartup(MAKEWORD(1, 1), &w))
5025  return -1;
5026  tcp_done = 1;
5027  }
5028 #endif
5029  return 0;
5030 }
5031 #endif
5032 
5033 /******************************************************************************/
5034 
5035 #ifndef WITH_NOIO
5036 static const char*
5038 {
5039  const char *msg = NULL;
5040  switch (soap->errmode)
5041  {
5042  case 0:
5043  msg = soap_strerror(soap);
5044  break;
5045  case 1:
5046  msg = "WSAStartup failed";
5047  break;
5048  case 2:
5049  {
5050 #ifndef WITH_LEAN
5052  if (!msg)
5053 #endif
5054  {
5055  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 37), "TCP/UDP IP error %d", soap->errnum);
5056  msg = soap->msgbuf;
5057  }
5058  }
5059  }
5060  return msg;
5061 }
5062 #endif
5063 
5064 /******************************************************************************/
5065 
5066 #if !defined(WITH_IPV6) || defined(WITH_COOKIES)
5067 #ifndef WITH_NOIO
5068 static int
5069 tcp_gethostbyname(struct soap *soap, const char *addr, struct hostent *hostent, struct in_addr *inaddr)
5070 {
5071 #if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
5072  struct hostent_data ht_data;
5073 #elif (!defined(__GLIBC__) || !defined(_GNU_SOURCE) || (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && defined(HAVE_GETHOSTBYNAME_R)
5074  int r;
5075  char *tmpbuf = soap->tmpbuf;
5076  size_t tmplen = sizeof(soap->tmpbuf);
5077 #elif defined(HAVE_GETHOSTBYNAME_R)
5078  char *tmpbuf = soap->tmpbuf;
5079  size_t tmplen = sizeof(soap->tmpbuf);
5080 #endif
5081 #ifdef VXWORKS
5082  int hostint; /* vxWorks compatible */
5083 #endif
5084  if (inaddr)
5085  {
5086  soap_int32 iadd = -1;
5087 #ifdef AS400
5088  iadd = inet_addr((void*)addr);
5089 #else
5090  iadd = inet_addr((char*)addr);
5091 #endif
5092  if (iadd != -1)
5093  {
5094  if (soap_memcpy((void*)inaddr, sizeof(struct in_addr), (const void*)&iadd, sizeof(iadd)))
5095  return soap->error = SOAP_EOM;
5096  return SOAP_OK;
5097  }
5098  }
5099 #if (defined(_AIX43) || defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R)
5100  memset((void*)&ht_data, 0, sizeof(ht_data));
5101  if (gethostbyname_r(addr, hostent, &ht_data) < 0)
5102  {
5103  hostent = NULL;
5104  soap->errnum = h_errno;
5105  }
5106 #elif (!defined(__GLIBC__) || !defined(_GNU_SOURCE) || (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && defined(HAVE_GETHOSTBYNAME_R)
5107  while ((r = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &hostent, &soap->errnum)) < 0)
5108  {
5109  if (tmpbuf != soap->tmpbuf)
5110  SOAP_FREE(soap, tmpbuf);
5111  if (r != SOAP_ERANGE)
5112  {
5113  hostent = NULL;
5114  break;
5115  }
5116  tmplen *= 2;
5117  tmpbuf = (char*)SOAP_MALLOC(soap, tmplen);
5118  if (!tmpbuf)
5119  break;
5120  }
5121 #elif defined(HAVE_GETHOSTBYNAME_R)
5122  hostent = gethostbyname_r(addr, hostent, tmpbuf, tmplen, &soap->errnum);
5123 #elif defined(VXWORKS)
5124  /* vxWorks compatible */
5125  /* If the DNS resolver library resolvLib has been configured in the vxWorks
5126  * image, a query for the host IP address is sent to the DNS server, if the
5127  * name was not found in the local host table. */
5128  hostint = hostGetByName((char*)addr);
5129  if (hostint == ERROR)
5130  {
5131  hostent = NULL;
5132  soap->errnum = soap_errno;
5133  }
5134 #else
5135 #ifdef AS400
5136  hostent = gethostbyname((void*)addr);
5137 #else
5138  hostent = gethostbyname((char*)addr);
5139 #endif
5140  if (!hostent)
5141  soap->errnum = h_errno;
5142 #endif
5143  if (!hostent)
5144  {
5145  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
5146  return SOAP_ERR;
5147  }
5148  if (inaddr)
5149  {
5150 #ifdef VXWORKS
5151  inaddr->s_addr = hostint; /* vxWorks compatible */
5152 #else
5153  if (soap_memcpy((void*)inaddr, sizeof(struct in_addr), (const void*)hostent->h_addr, (size_t)hostent->h_length))
5154  {
5155 #if (!defined(_AIX43) && !defined(TRU64) && !defined(HP_UX)) || !defined(HAVE_GETHOSTBYNAME_R)
5156 #if (!defined(__GLIBC__) || !defined(_GNU_SOURCE) || (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && defined(HAVE_GETHOSTBYNAME_R)
5157  if (tmpbuf && tmpbuf != soap->tmpbuf)
5158  SOAP_FREE(soap, tmpbuf);
5159 #endif
5160 #endif
5161  return soap->error = SOAP_EOM;
5162  }
5163 #endif
5164  }
5165 #if (!defined(__GLIBC__) || !defined(_GNU_SOURCE) || (!_GNU_SOURCE && !defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__ANDROID__) || defined(FREEBSD) || defined(__FreeBSD__)) && defined(HAVE_GETHOSTBYNAME_R)
5166  if (tmpbuf && tmpbuf != soap->tmpbuf)
5167  SOAP_FREE(soap, tmpbuf);
5168 #endif
5169  return SOAP_OK;
5170 }
5171 #endif
5172 #endif
5173 
5174 /******************************************************************************/
5175 
5176 #if !defined(WITH_IPV6)
5177 #ifndef WITH_NOIO
5178 static int
5179 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
5180 {
5181  struct hostent hostent;
5182  return tcp_gethostbyname(soap, addr, &hostent, inaddr);
5183 }
5184 #endif
5185 #endif
5186 
5187 /******************************************************************************/
5188 
5189 #ifndef WITH_NOIO
5190 static SOAP_SOCKET
5191 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
5192 {
5193 #ifdef WITH_IPV6
5194  struct addrinfo hints, *res, *ressave;
5195 #endif
5196  SOAP_SOCKET sk;
5197  int err = 0;
5198 #ifndef WITH_LEAN
5199  int set = 1;
5200 #endif
5201 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
5202  int retries;
5203 #endif
5204  soap->errnum = 0;
5205  soap->errmode = 0;
5207  {
5208  if ((soap->omode & SOAP_IO_UDP) && soap->socket == soap->master)
5209  {
5210 #ifdef IP_MULTICAST_TTL
5211 #ifndef WITH_IPV6
5212  soap->errmode = 2;
5213  if (soap->fresolve(soap, host, &soap->peer.in.sin_addr))
5214  {
5215  soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
5217  return soap->socket = SOAP_INVALID_SOCKET;
5218  }
5219  soap->peer.in.sin_port = htons((short)port);
5220  soap->errmode = 0;
5221 #else
5222  memset((void*)&hints, 0, sizeof(hints));
5223  err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
5224  if (err || !res)
5225  {
5226  soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
5228  return soap->socket = SOAP_INVALID_SOCKET;
5229  }
5230  if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen))
5231  {
5232  soap->error = SOAP_EOM;
5234  freeaddrinfo(res);
5235  return soap->socket = SOAP_INVALID_SOCKET;
5236  }
5237  soap->peerlen = res->ai_addrlen;
5238  freeaddrinfo(res);
5239 #endif
5240  if (soap->ipv4_multicast_ttl)
5241  {
5242  unsigned char ttl = soap->ipv4_multicast_ttl;
5243  if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
5244  {
5246  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
5248  return soap->socket = SOAP_INVALID_SOCKET;
5249  }
5250  }
5252  {
5253  if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
5254 #ifndef WINDOWS
5255  {
5257  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
5259  return soap->socket = SOAP_INVALID_SOCKET;
5260  }
5261 #else
5262 #ifndef IP_MULTICAST_IF
5263 #define IP_MULTICAST_IF 2
5264 #endif
5265  if (setsockopt(soap->socket, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
5266  {
5268  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
5270  return soap->socket = SOAP_INVALID_SOCKET;
5271  }
5272 #endif
5273  }
5274 #endif
5275  return soap->socket;
5276  }
5279  }
5280  if (tcp_init(soap))
5281  {
5282  soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
5283  return SOAP_INVALID_SOCKET;
5284  }
5285  soap->errmode = 0;
5286 #ifdef WITH_IPV6
5287  memset((void*)&hints, 0, sizeof(hints));
5288  hints.ai_family = PF_UNSPEC;
5289 #ifndef WITH_LEAN
5290  if ((soap->omode & SOAP_IO_UDP))
5291  hints.ai_socktype = SOCK_DGRAM;
5292  else
5293 #endif
5294  hints.ai_socktype = SOCK_STREAM;
5295  soap->errmode = 2;
5296  if (soap->proxy_host)
5297  err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
5298  else
5299  err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
5300  if (err || !res)
5301  {
5302  soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
5303  return SOAP_INVALID_SOCKET;
5304  }
5305  ressave = res;
5306 again:
5307  sk = soap->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
5308  soap->error = SOAP_OK;
5309  soap->errmode = 0;
5310 #else
5311 #ifndef WITH_LEAN
5312 again:
5313 #endif
5314 #ifndef WITH_LEAN
5315  if ((soap->omode & SOAP_IO_UDP))
5316  sk = soap->socket = socket(AF_INET, SOCK_DGRAM, 0);
5317  else
5318 #endif
5319  sk = soap->socket = socket(AF_INET, SOCK_STREAM, 0);
5320 #endif
5321  if (!soap_valid_socket(sk))
5322  {
5323 #ifdef WITH_IPV6
5324  if (res->ai_next)
5325  {
5326  res = res->ai_next;
5327  goto again;
5328  }
5329 #endif
5331  soap_set_receiver_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
5332 #ifdef WITH_IPV6
5333  freeaddrinfo(ressave);
5334 #endif
5335  return SOAP_INVALID_SOCKET;
5336  }
5337 #ifdef WITH_SOCKET_CLOSE_ON_EXIT
5338 #ifdef WIN32
5339 #ifndef UNDER_CE
5340  SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
5341 #endif
5342 #else
5343  fcntl(sk, F_SETFD, 1);
5344 #endif
5345 #endif
5346 #ifndef WITH_LEAN
5347  if ((soap->connect_flags & SO_LINGER))
5348  {
5349  struct linger linger;
5350  memset((void*)&linger, 0, sizeof(linger));
5351  linger.l_onoff = 1;
5352  linger.l_linger = soap->linger_time;
5353  if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
5354  {
5356  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
5357  soap->fclosesocket(soap, sk);
5358 #ifdef WITH_IPV6
5359  freeaddrinfo(ressave);
5360 #endif
5361  return soap->socket = SOAP_INVALID_SOCKET;
5362  }
5363  }
5364  if ((soap->connect_flags & ~SO_LINGER) && setsockopt(sk, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int)))
5365  {
5367 #ifdef WITH_IPV6
5368  freeaddrinfo(ressave);
5369 #endif
5370  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
5371  soap->fclosesocket(soap, sk);
5372  return soap->socket = SOAP_INVALID_SOCKET;
5373  }
5374 #ifndef UNDER_CE
5375  if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
5376  {
5378 #ifdef WITH_IPV6
5379  freeaddrinfo(ressave);
5380 #endif
5381  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
5382  soap->fclosesocket(soap, sk);
5383  return soap->socket = SOAP_INVALID_SOCKET;
5384  }
5385  if (soap->sndbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int)))
5386  {
5388 #ifdef WITH_IPV6
5389  freeaddrinfo(ressave);
5390 #endif
5391  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
5392  soap->fclosesocket(soap, sk);
5393  return soap->socket = SOAP_INVALID_SOCKET;
5394  }
5395  if (soap->rcvbuf > 0 && setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int)))
5396  {
5398 #ifdef WITH_IPV6
5399  freeaddrinfo(ressave);
5400 #endif
5401  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
5402  soap->fclosesocket(soap, sk);
5403  return soap->socket = SOAP_INVALID_SOCKET;
5404  }
5405 #ifdef TCP_KEEPIDLE
5406  if (soap->tcp_keep_idle && setsockopt(sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
5407  {
5409 #ifdef WITH_IPV6
5410  freeaddrinfo(ressave);
5411 #endif
5412  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
5413  soap->fclosesocket(soap, sk);
5414  return soap->socket = SOAP_INVALID_SOCKET;
5415  }
5416 #endif
5417 #ifdef TCP_KEEPINTVL
5418  if (soap->tcp_keep_intvl && setsockopt(sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
5419  {
5421 #ifdef WITH_IPV6
5422  freeaddrinfo(ressave);
5423 #endif
5424  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
5425  soap->fclosesocket(soap, sk);
5426  return soap->socket = SOAP_INVALID_SOCKET;
5427  }
5428 #endif
5429 #ifdef TCP_KEEPCNT
5430  if (soap->tcp_keep_cnt && setsockopt(sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
5431  {
5433 #ifdef WITH_IPV6
5434  freeaddrinfo(ressave);
5435 #endif
5436  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
5437  soap->fclosesocket(soap, sk);
5438  return soap->socket = SOAP_INVALID_SOCKET;
5439  }
5440 #endif
5441 #ifdef TCP_NODELAY
5442  if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
5443  {
5445 #ifdef WITH_IPV6
5446  freeaddrinfo(ressave);
5447 #endif
5448  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
5449  soap->fclosesocket(soap, sk);
5450  return soap->socket = SOAP_INVALID_SOCKET;
5451  }
5452 #endif
5453 #ifdef WITH_IPV6
5455  {
5456  struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
5457  in6addr->sin6_scope_id = soap->ipv6_multicast_if;
5458  }
5459 #endif
5460 #endif
5461 #ifdef IP_MULTICAST_TTL
5462  if ((soap->omode & SOAP_IO_UDP))
5463  {
5464  if (soap->ipv4_multicast_ttl)
5465  {
5466  unsigned char ttl = soap->ipv4_multicast_ttl;
5467  if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
5468  {
5470 #ifdef WITH_IPV6
5471  freeaddrinfo(ressave);
5472 #endif
5473  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
5474  soap->fclosesocket(soap, sk);
5475  return soap->socket = SOAP_INVALID_SOCKET;
5476  }
5477  }
5479  {
5480  if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
5481 #ifndef WINDOWS
5482  {
5484 #ifdef WITH_IPV6
5485  freeaddrinfo(ressave);
5486 #endif
5487  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
5488  soap->fclosesocket(soap, sk);
5489  return soap->socket = SOAP_INVALID_SOCKET;
5490  }
5491 #else
5492 #ifndef IP_MULTICAST_IF
5493 #define IP_MULTICAST_IF 2
5494 #endif
5495  if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
5496  {
5498 #ifdef WITH_IPV6
5499  freeaddrinfo(ressave);
5500 #endif
5501  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
5502  soap->fclosesocket(soap, sk);
5503  return soap->socket = SOAP_INVALID_SOCKET;
5504  }
5505 #endif
5506  }
5507  }
5508 #endif
5509 #endif
5510  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", (int)sk, host, port));
5511 #ifndef WITH_IPV6
5512  soap->peerlen = sizeof(soap->peer.in);
5513  memset((void*)&soap->peer.in, 0, sizeof(soap->peer.in));
5514  soap->peer.in.sin_family = AF_INET;
5515 #ifndef WIN32
5516  if (soap->client_addr)
5517  {
5518  struct sockaddr_in addr;
5519  memset((void*)&addr, 0, sizeof(addr));
5520  addr.sin_family = AF_INET;
5521  if (soap->client_port >= 0)
5522  addr.sin_port = htons(soap->client_port);
5523  if (inet_pton(AF_INET, soap->client_addr, (void*)&addr.sin_addr) != 1 || bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
5524  {
5526  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
5527  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
5528  soap->fclosesocket(soap, sk);
5529  soap->client_addr = NULL;
5530  soap->client_port = -1;
5531  return soap->socket = SOAP_INVALID_SOCKET;
5532  }
5533  soap->client_addr = NULL; /* disable bind before connect, so need to set it again before the next connect */
5534  soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */
5535  }
5536  else
5537 #endif
5538  if (soap->client_port >= 0)
5539  {
5540  struct sockaddr_in addr;
5541  memset((void*)&addr, 0, sizeof(addr));
5542  addr.sin_family = AF_INET;
5543  addr.sin_port = htons(soap->client_port);
5544  if (bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
5545  {
5547  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
5548  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
5549  soap->fclosesocket(soap, sk);
5550  soap->client_port = -1;
5551  return soap->socket = SOAP_INVALID_SOCKET;
5552  }
5553  soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */
5554  }
5555 #ifndef WIN32
5556  if (soap->client_interface)
5557  {
5558  if (inet_pton(AF_INET, soap->client_interface, &soap->peer.in.sin_addr) != 1)
5559  {
5561  soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR);
5562  soap->fclosesocket(soap, sk);
5564  return soap->socket = SOAP_INVALID_SOCKET;
5565  }
5566  soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */
5567  }
5568 #endif
5569  soap->errmode = 2;
5570  if (soap->proxy_host)
5571  {
5572  if (soap->fresolve(soap, soap->proxy_host, &soap->peer.in.sin_addr))
5573  {
5574  soap_set_receiver_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
5575  soap->fclosesocket(soap, sk);
5576  return soap->socket = SOAP_INVALID_SOCKET;
5577  }
5578  soap->peer.in.sin_port = htons((short)soap->proxy_port);
5579  }
5580  else
5581  {
5582  if (soap->fresolve(soap, host, &soap->peer.in.sin_addr))
5583  {
5584  soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
5585  soap->fclosesocket(soap, sk);
5586  return soap->socket = SOAP_INVALID_SOCKET;
5587  }
5588  soap->peer.in.sin_port = htons((short)port);
5589  }
5590  soap->errmode = 0;
5591 #ifndef WITH_LEAN
5592  if ((soap->omode & SOAP_IO_UDP))
5593  return sk;
5594 #endif
5595 #else
5596 #ifndef WIN32
5597  if (soap->client_addr)
5598  {
5599  struct sockaddr_in6 addr;
5600  memset((void*)&addr, 0, sizeof(addr));
5601  addr.sin6_family = AF_INET6;
5602  if ((soap->client_addr_ipv6 && res->ai_family == AF_INET6 && inet_pton(AF_INET6, soap->client_addr_ipv6, (void*)&addr.sin6_addr.s6_addr) == 1)
5603  || (!soap->client_addr_ipv6 && inet_pton(AF_INET6, soap->client_addr, (void*)&addr.sin6_addr.s6_addr) == 1)
5604  )
5605  {
5606  if (soap->client_port >= 0)
5607  addr.sin6_port = htons(soap->client_port);
5608  if (bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
5609  {
5611  freeaddrinfo(ressave);
5612  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
5613  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
5614  soap->fclosesocket(soap, sk);
5615  soap->client_addr = NULL;
5617  soap->client_port = -1;
5618  return soap->socket = SOAP_INVALID_SOCKET;
5619  }
5620  }
5621  else /* not an IPv6 address, must be IPv4 */
5622  {
5623  struct sockaddr_in addr;
5624  memset((void*)&addr, 0, sizeof(addr));
5625  addr.sin_family = AF_INET;
5626  if (soap->client_port >= 0)
5627  addr.sin_port = htons(soap->client_port);
5628  if (inet_pton(AF_INET, soap->client_addr, (void*)&addr.sin_addr) != 1 || bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
5629  {
5631  freeaddrinfo(ressave);
5632  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
5633  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
5634  soap->fclosesocket(soap, sk);
5635  soap->client_addr = NULL;
5637  soap->client_port = -1;
5638  return soap->socket = SOAP_INVALID_SOCKET;
5639  }
5640  }
5641  soap->client_addr = NULL; /* disable bind before connect, so need to set it again before the next connect */
5642  soap->client_addr_ipv6 = NULL; /* disable bind before connect, so need to set it again before the next connect */
5643  soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */
5644  }
5645  else
5646 #endif
5647  if (soap->client_port >= 0)
5648  {
5649  struct sockaddr_in6 addr;
5650  memset((void*)&addr, 0, sizeof(addr));
5651  addr.sin6_family = AF_INET6;
5652  addr.sin6_port = htons(soap->client_port);
5653  if (bind(sk, (struct sockaddr*)&addr, sizeof(addr)))
5654  {
5656  freeaddrinfo(ressave);
5657  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind before connect\n"));
5658  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in tcp_connect()", SOAP_TCP_ERROR);
5659  soap->fclosesocket(soap, sk);
5660  soap->client_port = -1;
5661  return soap->socket = SOAP_INVALID_SOCKET;
5662  }
5663  soap->client_port = -1; /* disable bind before connect, so need to set it again before the next connect */
5664  }
5665 #ifndef WIN32
5666  if (soap->client_interface)
5667  {
5668  if (inet_pton(AF_INET6, soap->client_interface, res->ai_addr) != 1)
5669  {
5670  if (inet_pton(AF_INET, soap->client_interface, res->ai_addr) != 1)
5671  {
5673  freeaddrinfo(ressave);
5674  soap_set_receiver_error(soap, tcp_error(soap), "inet_pton() failed in tcp_connect()", SOAP_TCP_ERROR);
5675  soap->fclosesocket(soap, sk);
5677  return soap->socket = SOAP_INVALID_SOCKET;
5678  }
5679  }
5680  soap->client_interface = NULL; /* disable client interface, so need to set it again before the next connect */
5681  }
5682 #endif
5683 #ifndef WITH_LEAN
5684  if ((soap->omode & SOAP_IO_UDP))
5685  {
5686  if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)res->ai_addr, res->ai_addrlen))
5687  {
5688  soap->error = SOAP_EOM;
5689  soap->fclosesocket(soap, sk);
5691  }
5692  soap->peerlen = res->ai_addrlen;
5693  freeaddrinfo(ressave);
5694  return sk;
5695  }
5696 #endif
5697 #endif
5698 #ifndef WITH_LEAN
5699  if (soap->connect_timeout)
5700  SOAP_SOCKNONBLOCK(sk)
5701  else
5702  SOAP_SOCKBLOCK(sk)
5703  retries = 10;
5704 #endif
5705  for (;;)
5706  {
5707 #ifdef WITH_IPV6
5708  if (connect(sk, res->ai_addr, (int)res->ai_addrlen))
5709 #else
5710  if (connect(sk, &soap->peer.addr, sizeof(soap->peer.in)))
5711 #endif
5712  {
5713  err = soap_socket_errno;
5714 #ifdef WITH_IPV6
5715  if (err == SOAP_ECONNREFUSED && res->ai_next)
5716  {
5717  soap->fclosesocket(soap, sk);
5718  res = res->ai_next;
5719  goto again;
5720  }
5721 #endif
5722 #ifndef WITH_LEAN
5723  if (err == SOAP_EADDRINUSE)
5724  {
5725  soap->fclosesocket(soap, sk);
5726  if (retries-- > 0)
5727  goto again;
5728  }
5729  else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
5730  {
5731  SOAP_SOCKLEN_T k;
5732  for (;;)
5733  {
5734  int r;
5735 #ifdef WITH_SELF_PIPE
5737  if ((r & SOAP_TCP_SELECT_PIP))
5738  {
5739  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection closed by self pipe\n"));
5740  soap->fclosesocket(soap, sk);
5741  return soap->socket = SOAP_INVALID_SOCKET;
5742  }
5743 #else
5745 #endif
5746  if (r > 0)
5747  break;
5748  if (!r)
5749  {
5750  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
5751  soap_set_receiver_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5752  soap->fclosesocket(soap, sk);
5753 #ifdef WITH_IPV6
5754  if (res->ai_next)
5755  {
5756  res = res->ai_next;
5757  goto again;
5758  }
5759  freeaddrinfo(ressave);
5760 #endif
5761  return soap->socket = SOAP_INVALID_SOCKET;
5762  }
5763  r = soap->errnum = soap_socket_errno;
5764  if (r != SOAP_EINTR)
5765  {
5766  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
5767  soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5768  soap->fclosesocket(soap, sk);
5769 #ifdef WITH_IPV6
5770  if (res->ai_next)
5771  {
5772  res = res->ai_next;
5773  goto again;
5774  }
5775  freeaddrinfo(ressave);
5776 #endif
5777  return soap->socket = SOAP_INVALID_SOCKET;
5778  }
5779  }
5780  k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
5781  if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
5782  break;
5783  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
5784  if (!soap->errnum)
5786  soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5787  soap->fclosesocket(soap, sk);
5788 #ifdef WITH_IPV6
5789  if (res->ai_next)
5790  {
5791  res = res->ai_next;
5792  goto again;
5793  }
5794  freeaddrinfo(ressave);
5795 #endif
5796  return soap->socket = SOAP_INVALID_SOCKET;
5797  }
5798 #endif
5799 #ifdef WITH_IPV6
5800  if (res->ai_next)
5801  {
5802  res = res->ai_next;
5803  soap->fclosesocket(soap, sk);
5804  goto again;
5805  }
5806 #endif
5807  if (err && err != SOAP_EINTR)
5808  {
5809  soap->errnum = err;
5810 #ifdef WITH_IPV6
5811  freeaddrinfo(ressave);
5812 #endif
5813  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
5814  soap_set_receiver_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
5815  soap->fclosesocket(soap, sk);
5816  return soap->socket = SOAP_INVALID_SOCKET;
5817  }
5818  }
5819  else
5820  {
5821  break;
5822  }
5823  }
5824 #ifdef WITH_IPV6
5825  soap->peerlen = 0; /* IPv6: already connected so use send() */
5826  freeaddrinfo(ressave);
5827 #endif
5828  soap->imode &= ~SOAP_ENC_SSL;
5829  soap->omode &= ~SOAP_ENC_SSL;
5830  if (endpoint && !soap_tag_cmp(endpoint, "https:*"))
5831  {
5832 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS) || defined(WITH_SYSTEMSSL)
5833 #ifdef WITH_OPENSSL
5834  BIO *bio;
5835 #endif
5836 #ifdef WITH_SYSTEMSSL
5837  gsk_iocallback local_io = { ssl_recv, ssl_send, NULL, NULL, NULL, NULL };
5838 #endif
5839  int r;
5840  if (soap->proxy_host)
5841  {
5842  soap_mode m = soap->mode; /* preserve settings */
5843  soap_mode om = soap->omode; /* make sure we only parse HTTP */
5844  ULONG64 count = soap->count; /* save the content length */
5845  const char *http_content = soap->http_content; /* save http_content when set */
5846  const char *http_extra_header = soap->http_extra_header; /* save http_extra_header when set */
5847  const char *bearer = soap->bearer; /* save bearer when set */
5848  int status = soap->status; /* save the current status/command */
5849  int keep_alive = soap->keep_alive; /* save the KA status */
5850  const char *userid, *passwd;
5851  soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
5853  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint));
5854 #ifdef WITH_NTLM
5855  if (soap->ntlm_challenge && soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port))
5856  {
5857  soap->fclosesocket(soap, sk);
5858  return soap->socket = SOAP_INVALID_SOCKET;
5859  }
5860 #endif
5861  if (soap_init_send(soap))
5862  {
5863  soap->fclosesocket(soap, sk);
5864  return soap->socket = SOAP_INVALID_SOCKET;
5865  }
5867  if (!soap->keep_alive)
5868  soap->keep_alive = -1; /* must keep alive */
5869  soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0);
5871  {
5872  soap->fclosesocket(soap, sk);
5873  return soap->socket = SOAP_INVALID_SOCKET;
5874  }
5875  soap->keep_alive = keep_alive;
5876  soap->omode = om;
5877  om = soap->imode; /* preserve */
5878  soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
5879  userid = soap->userid; /* preserve */
5880  passwd = soap->passwd; /* preserve */
5881  soap->error = soap->fparse(soap);
5882  if (soap->error)
5883  {
5884  soap->fclosesocket(soap, sk);
5885  return soap->socket = SOAP_INVALID_SOCKET;
5886  }
5887  soap->status = status; /* restore */
5888  soap->userid = userid; /* restore */
5889  soap->passwd = passwd; /* restore */
5890  soap->imode = om; /* restore */
5891  soap->count = count; /* restore */
5892  soap->http_content = http_content; /* restore */
5893  soap->http_extra_header = http_extra_header; /* restore */
5894  soap->bearer = bearer; /* restore */
5895  if (soap_init_send(soap))
5896  {
5897  soap->fclosesocket(soap, sk);
5898  return soap->socket = SOAP_INVALID_SOCKET;
5899  }
5900  if (endpoint)
5901  soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint); /* restore */
5902  soap->mode = m;
5903  }
5904 #ifdef WITH_OPENSSL
5905  ERR_clear_error();
5907  if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
5908  {
5909  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
5910  soap->fclosesocket(soap, sk);
5912  return soap->socket = SOAP_INVALID_SOCKET;
5913  }
5914  if (!soap->ssl)
5915  {
5916  soap->ssl = SSL_new(soap->ctx);
5917  if (!soap->ssl)
5918  {
5919  soap->fclosesocket(soap, sk);
5921  return soap->socket = SOAP_INVALID_SOCKET;
5922  }
5923  }
5924  else
5925  {
5926  SSL_clear(soap->ssl);
5927  }
5928  if (soap->session)
5929  {
5930  if (!strcmp(soap->session_host, host) && soap->session_port == port)
5931  SSL_set_session(soap->ssl, soap->session);
5932  SSL_SESSION_free(soap->session);
5933  soap->session = NULL;
5934  }
5935 #if OPENSSL_VERSION_NUMBER >= 0x1000000aL
5936  if (!(soap->ssl_flags & SOAP_SSLv3) && !SSL_set_tlsext_host_name(soap->ssl, host))
5937  {
5938  soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR);
5939  soap->fclosesocket(soap, sk);
5940  return soap->socket = SOAP_INVALID_SOCKET;
5941  }
5942 #elif (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && defined(SSL_CTRL_SET_TLSEXT_HOSTNAME)
5943  if (!SSL_ctrl(soap->ssl, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, (void*)host))
5944  {
5945  soap_set_receiver_error(soap, "SSL/TLS error", "SNI failed", SOAP_SSL_ERROR);
5946  soap->fclosesocket(soap, sk);
5947  return soap->socket = SOAP_INVALID_SOCKET;
5948  }
5949 #endif
5950  bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
5951  SSL_set_bio(soap->ssl, bio, bio);
5953  {
5954  /* Set SSL connect timeout and set SSL sockets to non-blocking */
5956  if (soap->connect_timeout > 0 && t < soap->connect_timeout)
5957  t = soap->connect_timeout;
5958  if (t > 0)
5959  retries = 10 * t;
5960  else if (t > -100000)
5961  retries = 1;
5962  else
5963  retries = t/-100000;
5964  SOAP_SOCKNONBLOCK(sk)
5965  }
5966  else
5967  {
5968  /* Set sockets to blocking */
5969  retries = 1;
5970  SOAP_SOCKBLOCK(sk)
5971  }
5972  err = SSL_ERROR_NONE;
5973  /* Try connecting until success or timeout */
5974  do
5975  {
5976  if ((r = SSL_connect(soap->ssl)) <= 0)
5977  {
5978  err = SSL_get_error(soap->ssl, r);
5979  if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
5980  {
5981  int s;
5982  if (err == SSL_ERROR_WANT_READ)
5984  else
5986  if (s < 0)
5987  break;
5988  if (s == 0 && retries-- <= 0)
5989  {
5990  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
5991  soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
5992  soap->fclosesocket(soap, sk);
5993  return soap->socket = SOAP_INVALID_SOCKET;
5994  }
5995  }
5996  else
5997  {
5999  break;
6000  }
6001  }
6002  } while (!SSL_is_init_finished(soap->ssl));
6003  if (r <= 0)
6004  {
6005  soap_set_sender_error(soap, soap_ssl_error(soap, r, err), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
6006  soap->fclosesocket(soap, sk);
6007  return soap->socket = SOAP_INVALID_SOCKET;
6008  }
6009  /* Check server credentials when required */
6011  {
6012  if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
6013  {
6014  soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
6015  soap->fclosesocket(soap, sk);
6016  return soap->socket = SOAP_INVALID_SOCKET;
6017  }
6019  {
6020  X509_NAME *subj;
6021  STACK_OF(CONF_VALUE) *val = NULL;
6022 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
6023  GENERAL_NAMES *names = NULL;
6024 #else
6025  int ext_count;
6026 #endif
6027  int ok = 0;
6028  X509 *peer = SSL_get_peer_certificate(soap->ssl);
6029  if (!peer)
6030  {
6031  soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
6032  soap->fclosesocket(soap, sk);
6033  return soap->socket = SOAP_INVALID_SOCKET;
6034  }
6035 #if OPENSSL_VERSION_NUMBER < 0x0090800fL
6036  ext_count = X509_get_ext_count(peer);
6037  if (ext_count > 0)
6038  {
6039  int i;
6040  for (i = 0; i < ext_count; i++)
6041  {
6042  X509_EXTENSION *ext = X509_get_ext(peer, i);
6043  const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
6044  if (ext_str && !strcmp(ext_str, "subjectAltName"))
6045  {
6046  X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
6047  unsigned char *data;
6048  if (!meth)
6049  break;
6050  data = ext->value->data;
6051  if (data)
6052  {
6053 #if OPENSSL_VERSION_NUMBER > 0x00907000L
6054  void *ext_data;
6055  if (meth->it)
6056  ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
6057  else
6058  {
6059 #if OPENSSL_VERSION_NUMBER > 0x0090800fL
6060  ext_data = meth->d2i(NULL, (const unsigned char **)&data, ext->value->length);
6061 #else
6062  ext_data = meth->d2i(NULL, &data, ext->value->length);
6063 #endif
6064  }
6065  if (ext_data)
6066  val = meth->i2v(meth, ext_data, NULL);
6067  else
6068  val = NULL;
6069  if (meth->it)
6070  ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
6071  else
6072  meth->ext_free(ext_data);
6073 #else
6074  void *ext_data = meth->d2i(NULL, &data, ext->value->length);
6075  if (ext_data)
6076  val = meth->i2v(meth, ext_data, NULL);
6077  meth->ext_free(ext_data);
6078 #endif
6079  if (val)
6080  {
6081  int j;
6082  for (j = 0; j < sk_CONF_VALUE_num(val); j++)
6083  {
6084  CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
6085  if (nval && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value))
6086  {
6087  ok = 1;
6088  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value));
6089  break;
6090  }
6091  else
6092  {
6093  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value));
6094  }
6095  }
6096  sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
6097  }
6098  }
6099  }
6100  if (ok)
6101  break;
6102  }
6103  }
6104 #else
6105  names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
6106  if (names)
6107  {
6108  val = i2v_GENERAL_NAMES(NULL, names, val);
6109  sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
6110  }
6111  if (val)
6112  {
6113  int j;
6114  for (j = 0; j < sk_CONF_VALUE_num(val); j++)
6115  {
6116  CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
6117  if (nval && (!strcmp(nval->name, "DNS") || !strcmp(nval->name, "IP Address")) && !soap_tag_cmp(host, nval->value))
6118  {
6119  ok = 1;
6120  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate %s %s\n", host, nval->name, nval->value));
6121  break;
6122  }
6123  else
6124  {
6125  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s %s\n", host, nval->name, nval->value));
6126  }
6127  }
6128  sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
6129  }
6130 #endif
6131  if (!ok && (subj = X509_get_subject_name(peer)) != 0)
6132  {
6133  int i = -1;
6134  do
6135  {
6136  ASN1_STRING *name;
6137  i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
6138  if (i == -1)
6139  break;
6140  name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
6141  if (name)
6142  {
6143 #if OPENSSL_VERSION_NUMBER < 0x10100000L
6144  const char *tmp = (const char*)ASN1_STRING_data(name);
6145 #else
6146  const char *tmp = (const char*)ASN1_STRING_get0_data(name);
6147 #endif
6148  if (!soap_tag_cmp(host, tmp))
6149  {
6150  ok = 1;
6151  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
6152  }
6153  else
6154  {
6155  unsigned char *tmp = NULL;
6156  ASN1_STRING_to_UTF8(&tmp, name);
6157  if (tmp)
6158  {
6159  if (!soap_tag_cmp(host, (const char*)tmp))
6160  {
6161  ok = 1;
6162  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
6163  }
6164  else if (tmp[0] == '*') /* wildcard domain */
6165  {
6166  const char *t = strchr(host, '.');
6167  if (t && !soap_tag_cmp(t, (const char*)tmp + 1))
6168  {
6169  ok = 1;
6170  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s match with certificate subject %s\n", host, tmp));
6171  }
6172  }
6173  else
6174  {
6175  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL: host name %s mismatch with certificate %s\n", host, tmp));
6176  }
6177  OPENSSL_free(tmp);
6178  }
6179  }
6180  }
6181  } while (!ok);
6182  }
6183  X509_free(peer);
6184  if (!ok)
6185  {
6186  soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
6187  soap->fclosesocket(soap, sk);
6188  return soap->socket = SOAP_INVALID_SOCKET;
6189  }
6190  }
6191  }
6192 #endif
6193 #ifdef WITH_GNUTLS
6195  if (!soap->session && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
6196  {
6197  soap->fclosesocket(soap, sk);
6198  return soap->socket = SOAP_INVALID_SOCKET;
6199  }
6200  gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
6202  {
6203  /* Set SSL connect timeout and set SSL sockets to non-blocking */
6205  if (soap->connect_timeout > 0 && t < soap->connect_timeout)
6206  t = soap->connect_timeout;
6207  if (t > 0)
6208  retries = 10 * t;
6209  else if (t > -100000)
6210  retries = 1;
6211  else
6212  retries = t/-100000;
6213  SOAP_SOCKNONBLOCK(sk)
6214  }
6215  else
6216  {
6217  /* Set sockets to blocking */
6218  retries = 1;
6219  SOAP_SOCKBLOCK(sk)
6220  }
6221  /* Try connecting until success or timeout */
6222  while ((r = gnutls_handshake(soap->session)))
6223  {
6224  /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
6225  if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
6226  {
6227  int s;
6228  if (!gnutls_record_get_direction(soap->session))
6230  else
6232  if (s < 0)
6233  break;
6234  if (s == 0 && retries-- <= 0)
6235  {
6236  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
6237  soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
6238  soap->fclosesocket(soap, sk);
6239  return soap->socket = SOAP_INVALID_SOCKET;
6240  }
6241  }
6242  else
6243  {
6245  break;
6246  }
6247  }
6248  if (r)
6249  {
6250  soap_set_sender_error(soap, soap_ssl_error(soap, r, 0), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
6251  soap->fclosesocket(soap, sk);
6252  return soap->socket = SOAP_INVALID_SOCKET;
6253  }
6255  {
6256  const char *s = ssl_verify(soap, host);
6257  if (s)
6258  {
6259  soap->fclosesocket(soap, sk);
6260  soap->error = soap_set_sender_error(soap, "SSL/TLS verify error", s, SOAP_SSL_ERROR);
6261  return soap->socket = SOAP_INVALID_SOCKET;
6262  }
6263  }
6264 #endif
6265 #ifdef WITH_SYSTEMSSL
6267  if (!soap->ctx && (soap->error = soap->fsslauth(soap)) != SOAP_OK)
6268  {
6269  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
6270  soap->fclosesocket(soap, sk);
6272  return soap->socket = SOAP_INVALID_SOCKET;
6273  }
6275  {
6276  /* Set SSL connect timeout and set SSL sockets to non-blocking */
6278  if (soap->connect_timeout > 0 && t < soap->connect_timeout)
6279  t = soap->connect_timeout;
6280  if (t > 0)
6281  retries = 10 * t;
6282  else if (t > -100000)
6283  retries = 1;
6284  else
6285  retries = t/-100000;
6286  SOAP_SOCKNONBLOCK(sk)
6287  }
6288  else
6289  {
6290  /* Set sockets to blocking */
6291  retries = 1;
6292  SOAP_SOCKBLOCK(sk)
6293  }
6294  r = gsk_secure_socket_open(soap->ctx, &soap->ssl);
6295  if (r == GSK_OK)
6296  r = gsk_attribute_set_numeric_value(soap->ssl, GSK_FD, sk);
6297  if (r == GSK_OK)
6298  r = gsk_attribute_set_buffer(soap->ssl, GSK_KEYRING_LABEL, soap->cafile, 0); /* Certificate label */
6299  if (r == GSK_OK)
6300  r = gsk_attribute_set_enum(soap->ssl, GSK_SESSION_TYPE, GSK_CLIENT_SESSION);
6301  if (r == GSK_OK)
6302  r = gsk_attribute_set_buffer(soap->ssl, GSK_V3_CIPHER_SPECS_EXPANDED, "0035002F000A", 0);
6303  if (r == GSK_OK)
6304  r = gsk_attribute_set_enum(soap->ssl, GSK_V3_CIPHERS, GSK_V3_CIPHERS_CHAR4);
6305  if (r == GSK_OK)
6306  r = gsk_attribute_set_callback(soap->ssl, GSK_IO_CALLBACK, &local_io);
6307  if (r != GSK_OK)
6308  {
6309  soap_set_receiver_error(soap, gsk_strerror(r), "SYSTEM SSL error in tcp_connect()", SOAP_SSL_ERROR);
6310  return soap->socket = SOAP_INVALID_SOCKET;
6311  }
6312  /* Try connecting until success or timeout */
6313  while ((r = gsk_secure_socket_init(soap->ssl)) != GSK_OK)
6314  {
6315  if (r == GSK_WOULD_BLOCK_READ || r == GSK_WOULD_BLOCK_WRITE)
6316  {
6317  int s;
6318  if (r == GSK_WOULD_BLOCK_READ)
6320  else
6322  if (s < 0)
6323  break;
6324  if (s == 0 && retries-- <= 0)
6325  {
6326  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
6327  soap_set_receiver_error(soap, "Timeout", "SSL_connect() failed in tcp_connect()", SOAP_TCP_ERROR);
6328  soap->fclosesocket(soap, sk);
6329  return soap->socket = SOAP_INVALID_SOCKET;
6330  }
6331  }
6332  else
6333  {
6335  break;
6336  }
6337  }
6338  if (r != GSK_OK)
6339  {
6340  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
6341  soap_set_receiver_error(soap, gsk_strerror(r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
6342  soap->fclosesocket(soap, sk);
6343  return soap->socket = SOAP_INVALID_SOCKET;
6344  }
6345 #endif
6346  soap->imode |= SOAP_ENC_SSL;
6347  soap->omode |= SOAP_ENC_SSL;
6348 #else
6349  soap->fclosesocket(soap, sk);
6351  return soap->socket = SOAP_INVALID_SOCKET;
6352 #endif
6353  }
6355  SOAP_SOCKNONBLOCK(sk)
6356  else
6357  SOAP_SOCKBLOCK(sk)
6358  return sk;
6359 }
6360 #endif
6361 
6362 /******************************************************************************/
6363 
6364 #ifndef WITH_NOIO
6365 static int
6366 tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
6367 {
6368  int r;
6369  struct timeval tv;
6370  fd_set fd[3], *rfd, *sfd, *efd;
6371  int retries = 0;
6372  int eintr = SOAP_MAXEINTR;
6373  soap->errnum = 0;
6374  if (!soap_valid_socket(sk))
6375  {
6376  soap->error = SOAP_EOF;
6377  return -1;
6378  }
6379 #ifndef WIN32
6380 #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
6381  /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */
6382  if (1)
6383 #else
6384  /* if fd max set size exceeded, use poll() when available */
6385  if ((int)sk >= (int)FD_SETSIZE)
6386 #endif
6387 #ifdef HAVE_POLL
6388  {
6389 #ifdef WITH_SELF_PIPE
6390  struct pollfd pollfd[2];
6391  pollfd[1].fd = soap->pipe_fd[0];
6392  pollfd[1].events = POLLIN;
6393 #else
6394  struct pollfd pollfd[1];
6395 #endif
6396  pollfd[0].fd = (int)sk;
6397  pollfd[0].events = 0;
6398  if ((flags & SOAP_TCP_SELECT_RCV))
6399  pollfd[0].events |= POLLIN;
6400  if ((flags & SOAP_TCP_SELECT_SND))
6401  pollfd[0].events |= POLLOUT;
6402  if ((flags & SOAP_TCP_SELECT_ERR))
6403  pollfd[0].events |= POLLERR;
6404  if (timeout <= 0)
6405  timeout /= -1000; /* -usec -> ms */
6406  else
6407  {
6408  retries = timeout - 1;
6409  timeout = 1000;
6410  }
6411  do
6412  {
6413 #ifdef WITH_SELF_PIPE
6414  r = poll(pollfd, 2, timeout);
6415 #else
6416  r = poll(pollfd, 1, timeout);
6417 #endif
6418  if (r < 0 && (soap->errnum = soap_socket_errno) == SOAP_EINTR && eintr > 0)
6419  {
6420  eintr--;
6421  r = 0;
6422  }
6423  else if (retries-- <= 0)
6424  {
6425  break;
6426  }
6427  } while (r == 0);
6428  if (r > 0)
6429  {
6430  r = 0;
6431  if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd[0].revents & POLLIN))
6432  r |= SOAP_TCP_SELECT_RCV;
6433  if ((flags & SOAP_TCP_SELECT_SND) && (pollfd[0].revents & POLLOUT))
6434  r |= SOAP_TCP_SELECT_SND;
6435  if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd[0].revents & POLLERR))
6436  r |= SOAP_TCP_SELECT_ERR;
6437 #ifdef WITH_SELF_PIPE
6438  if ((flags & SOAP_TCP_SELECT_PIP) && (pollfd[1].revents & POLLIN))
6439  {
6440  char ch;
6441  for (;;)
6442  {
6443  if (read(soap->pipe_fd[0], &ch, 1) == -1)
6444  {
6446  break;
6447  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n"));
6448  return -1;
6449  }
6450  }
6451  r |= SOAP_TCP_SELECT_PIP;
6452  }
6453 #endif
6454  }
6455  else if (r == 0)
6456  {
6457  soap->errnum = 0;
6458  }
6459  return r;
6460  }
6461 #else
6462  {
6464  return -1;
6465  }
6466 #endif
6467 #endif
6468  if (timeout > 0)
6469  retries = timeout - 1;
6470  do
6471  {
6472  rfd = sfd = efd = NULL;
6473 #ifdef WITH_SELF_PIPE
6474  if ((flags & SOAP_TCP_SELECT_PIP) || (flags & SOAP_TCP_SELECT_RCV))
6475  {
6476  rfd = &fd[0];
6477  FD_ZERO(rfd);
6478  if ((flags & SOAP_TCP_SELECT_PIP))
6479  FD_SET(soap->pipe_fd[0], rfd);
6480  if ((flags & SOAP_TCP_SELECT_RCV))
6481  FD_SET(sk, rfd);
6482  }
6483 #else
6484  if ((flags & SOAP_TCP_SELECT_RCV))
6485  {
6486  rfd = &fd[0];
6487  FD_ZERO(rfd);
6488  FD_SET(sk, rfd);
6489  }
6490 #endif
6491  if ((flags & SOAP_TCP_SELECT_SND))
6492  {
6493  sfd = &fd[1];
6494  FD_ZERO(sfd);
6495  FD_SET(sk, sfd);
6496  }
6497  if ((flags & SOAP_TCP_SELECT_ERR))
6498  {
6499  efd = &fd[2];
6500  FD_ZERO(efd);
6501  FD_SET(sk, efd);
6502  }
6503  if (timeout <= 0)
6504  {
6505  tv.tv_sec = -timeout / 1000000;
6506  tv.tv_usec = -timeout % 1000000;
6507  }
6508  else
6509  {
6510  tv.tv_sec = 1;
6511  tv.tv_usec = 0;
6512  }
6513 #ifdef WITH_SELF_PIPE
6514  r = select((int)(sk > soap->pipe_fd[0] ? sk : soap->pipe_fd[0]) + 1, rfd, sfd, efd, &tv);
6515 #else
6516  r = select((int)sk + 1, rfd, sfd, efd, &tv);
6517 #endif
6518  if (r < 0 && (soap->errnum = soap_socket_errno) == SOAP_EINTR && eintr > 0)
6519  {
6520  eintr--;
6521  r = 0;
6522  }
6523  else if (retries-- <= 0)
6524  {
6525  break;
6526  }
6527  } while (r == 0);
6528  if (r > 0)
6529  {
6530  r = 0;
6531  if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd))
6532  r |= SOAP_TCP_SELECT_RCV;
6533  if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd))
6534  r |= SOAP_TCP_SELECT_SND;
6535  if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd))
6536  r |= SOAP_TCP_SELECT_ERR;
6537 #ifdef WITH_SELF_PIPE
6538  if ((flags & SOAP_TCP_SELECT_PIP) && FD_ISSET(soap->pipe_fd[0], rfd))
6539  {
6540  char ch;
6541  for (;;)
6542  {
6543  if (read(soap->pipe_fd[0], &ch, 1) == -1)
6544  {
6546  break;
6547  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Self pipe read error\n"));
6548  return -1;
6549  }
6550  }
6551  r |= SOAP_TCP_SELECT_PIP;
6552  }
6553 #endif
6554  }
6555  else if (r == 0)
6556  {
6557  soap->errnum = 0;
6558  }
6559  return r;
6560 }
6561 #endif
6562 
6563 /******************************************************************************/
6564 
6565 #ifndef WITH_NOIO
6566 static SOAP_SOCKET
6567 tcp_accept(struct soap *soap, SOAP_SOCKET sk, struct sockaddr *addr, int *len)
6568 {
6569  SOAP_SOCKET s;
6570  (void)soap;
6571  s = accept(sk, addr, (SOAP_SOCKLEN_T*)len); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
6572 #ifdef WITH_SOCKET_CLOSE_ON_EXIT
6573 #ifdef WIN32
6574 #ifndef UNDER_CE
6575  SetHandleInformation((HANDLE)s, HANDLE_FLAG_INHERIT, 0);
6576 #endif
6577 #else
6578  fcntl(s, F_SETFD, FD_CLOEXEC);
6579 #endif
6580 #endif
6581  return s;
6582 }
6583 #endif
6584 
6585 /******************************************************************************/
6586 
6587 #ifndef WITH_NOIO
6588 static int
6590 {
6591 #ifdef WITH_OPENSSL
6592  if (soap->ssl)
6593  {
6594  int r;
6595  if (soap->session)
6596  {
6597  SSL_SESSION_free(soap->session);
6598  soap->session = NULL;
6599  }
6600  if (*soap->host)
6601  {
6602  soap->session = SSL_get1_session(soap->ssl);
6603  if (soap->session)
6604  {
6606  soap->session_port = soap->port;
6607  }
6608  }
6610  {
6611  r = SSL_shutdown(soap->ssl);
6612  /* SSL shutdown does not work when reads are pending, non-blocking */
6613  if (r == 0)
6614  {
6615  while (SSL_want_read(soap->ssl))
6616  {
6617  if (SSL_read(soap->ssl, NULL, 0)
6619  {
6620  r = SSL_shutdown(soap->ssl);
6621  break;
6622  }
6623  }
6624  }
6625  if (r == 0 && !soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR))
6626  {
6627 #if !defined(WITH_LEAN) && !defined(WIN32)
6628  /*
6629  wait up to 5 seconds for close_notify to be sent by peer (if peer not
6630  present, this avoids calling SSL_shutdown() which has a lengthy return
6631  timeout)
6632  */
6634  if (r <= 0)
6635  {
6636  soap->errnum = 0;
6637  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
6640  ERR_clear_error();
6641  SSL_free(soap->ssl);
6642  soap->ssl = NULL;
6643  return SOAP_OK;
6644  }
6645 #else
6646  r = SSL_shutdown(soap->ssl);
6647  if (r <= 0)
6648  {
6649  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
6651  {
6654  }
6655  }
6656 #endif
6657  }
6658  }
6659  SSL_free(soap->ssl);
6660  soap->ssl = NULL;
6661  ERR_clear_error();
6662  }
6663 #endif
6664 #ifdef WITH_GNUTLS
6665  if (soap->session)
6666  {
6667  gnutls_bye(soap->session, GNUTLS_SHUT_RDWR);
6668  gnutls_deinit(soap->session);
6669  soap->session = NULL;
6670  }
6671 #endif
6672 #ifdef WITH_SYSTEMSSL
6673  if (soap->ssl)
6674  {
6675  gsk_secure_socket_shutdown(soap->ssl);
6676  gsk_secure_socket_close(&soap->ssl);
6677  }
6678 #endif
6680  {
6684  }
6685  return SOAP_OK;
6686 }
6687 #endif
6688 
6689 /******************************************************************************/
6690 
6691 #ifndef WITH_NOIO
6692 static int
6694 {
6695  (void)soap;
6696  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk));
6697  return soap_closesocket(sk);
6698 }
6699 #endif
6700 
6701 /******************************************************************************/
6702 
6703 #ifndef WITH_NOIO
6704 static int
6706 {
6707  (void)soap;
6708  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how));
6709  return shutdown(sk, how);
6710 }
6711 #endif
6712 
6713 /******************************************************************************/
6714 
6715 #ifndef WITH_NOIO
6716 SOAP_FMAC1
6718 SOAP_FMAC2
6719 soap_bind(struct soap *soap, const char *host, int port, int backlog)
6720 {
6721 #if defined(WITH_IPV6)
6722  struct addrinfo *addrinfo = NULL;
6723  struct addrinfo hints;
6724  struct addrinfo res;
6725  int err;
6726  int set = 1;
6727  int unset = 0;
6728 #elif !defined(WITH_LEAN)
6729  int set = 1;
6730 #endif
6732  {
6735  }
6737  soap->errnum = 0;
6738  soap->errmode = 1;
6739  if (tcp_init(soap))
6740  {
6741  soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
6742  return SOAP_INVALID_SOCKET;
6743  }
6744 #ifdef WITH_IPV6
6745  memset((void*)&hints, 0, sizeof(hints));
6746  hints.ai_family = soap->bind_inet6 ? AF_INET6 : PF_UNSPEC;
6747 #ifndef WITH_LEAN
6748  if ((soap->omode & SOAP_IO_UDP))
6749  hints.ai_socktype = SOCK_DGRAM;
6750  else
6751 #endif
6752  hints.ai_socktype = SOCK_STREAM;
6753  hints.ai_flags = AI_PASSIVE;
6754  soap->errmode = 2;
6755  err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
6756  if (err || !addrinfo)
6757  {
6758  soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
6759  if (addrinfo)
6760  freeaddrinfo(addrinfo);
6761  return SOAP_INVALID_SOCKET;
6762  }
6763  res = *addrinfo;
6764  if (soap_memcpy((void*)&soap->peer.storage, sizeof(soap->peer.storage), (const void*)addrinfo->ai_addr, addrinfo->ai_addrlen))
6765  {
6766  freeaddrinfo(addrinfo);
6767  soap->error = SOAP_EOM;
6768  return SOAP_INVALID_SOCKET;
6769  }
6770  soap->peerlen = addrinfo->ai_addrlen;
6771  res.ai_addr = &soap->peer.addr;
6772  res.ai_addrlen = soap->peerlen;
6773  freeaddrinfo(addrinfo);
6774  soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
6775 #else
6776 #ifndef WITH_LEAN
6777  if ((soap->omode & SOAP_IO_UDP))
6778  soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
6779  else
6780 #endif
6781  soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
6782 #endif
6783  soap->errmode = 0;
6784  if (!soap_valid_socket(soap->master))
6785  {
6787  soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
6788  return SOAP_INVALID_SOCKET;
6789  }
6790  soap->port = port;
6791 #ifndef WITH_LEAN
6792  if ((soap->omode & SOAP_IO_UDP))
6793  soap->socket = soap->master;
6794 #endif
6795 #ifdef WITH_SOCKET_CLOSE_ON_EXIT
6796 #ifdef WIN32
6797 #ifndef UNDER_CE
6798  SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
6799 #endif
6800 #else
6801  fcntl(soap->master, F_SETFD, 1);
6802 #endif
6803 #endif
6804 #ifndef WITH_LEAN
6805  if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
6806  {
6808  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
6809  return SOAP_INVALID_SOCKET;
6810  }
6811 #ifndef UNDER_CE
6812  if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
6813  {
6815  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
6816  return SOAP_INVALID_SOCKET;
6817  }
6818  if (soap->sndbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int)))
6819  {
6821  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
6822  return SOAP_INVALID_SOCKET;
6823  }
6824  if (soap->rcvbuf > 0 && setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int)))
6825  {
6827  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
6828  return SOAP_INVALID_SOCKET;
6829  }
6830 #ifdef TCP_NODELAY
6831  if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
6832  {
6834  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
6835  return SOAP_INVALID_SOCKET;
6836  }
6837 #endif
6838 #ifdef TCP_FASTOPEN
6839  if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_FASTOPEN, (char*)&set, sizeof(int)))
6840  {
6841  /* silently ignore */
6842  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "setsockopt TCP_FASTOPEN failed in soap_bind()\n"));
6843  }
6844 #endif
6845 #endif
6846 #endif
6847 #ifdef WITH_IPV6
6848  if (res.ai_family == AF_INET6 && setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, soap->bind_v6only ? (char*)&set : (char*)&unset, sizeof(int)))
6849  {
6851  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
6852  return SOAP_INVALID_SOCKET;
6853  }
6854  soap->errmode = 0;
6855  if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
6856  {
6858  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n"));
6860  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
6861  return SOAP_INVALID_SOCKET;
6862  }
6863 #else
6864  soap->peerlen = sizeof(soap->peer.in);
6865  memset((void*)&soap->peer.in, 0, sizeof(soap->peer.in));
6866  soap->peer.in.sin_family = AF_INET;
6867  soap->errmode = 2;
6868  if (host)
6869  {
6870  if (soap->fresolve(soap, host, &soap->peer.in.sin_addr))
6871  {
6872  soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
6873  return SOAP_INVALID_SOCKET;
6874  }
6875  }
6876  else
6877  soap->peer.in.sin_addr.s_addr = htonl(INADDR_ANY);
6878  soap->peer.in.sin_port = htons((short)port);
6879  soap->errmode = 0;
6880  if (bind(soap->master, &soap->peer.addr, (int)soap->peerlen))
6881  {
6883  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, bind failed\n"));
6885  soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
6886  return SOAP_INVALID_SOCKET;
6887  }
6888 #endif
6889  if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
6890  {
6892  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host, listen failed\n"));
6894  soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
6895  return SOAP_INVALID_SOCKET;
6896  }
6897  return soap->master;
6898 }
6899 #endif
6900 
6901 /******************************************************************************/
6902 
6903 #ifndef WITH_NOIO
6904 SOAP_FMAC1
6905 int
6906 SOAP_FMAC2
6908 {
6909 #ifndef WITH_LEAN
6910  int r;
6912  {
6914  if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
6915  r = -1;
6916  }
6917  else if (soap_valid_socket(soap->master))
6918  {
6920  }
6921  else
6922  {
6923  return SOAP_OK; /* OK when no socket! */
6924  }
6925  if (r > 0)
6926  {
6927  int t;
6928 #ifdef WITH_OPENSSL
6929  if ((soap->imode & SOAP_ENC_SSL) && soap->ssl)
6930  {
6932  && (r & SOAP_TCP_SELECT_SND)
6933  && (!(r & SOAP_TCP_SELECT_RCV)
6934  || SSL_peek(soap->ssl, (char*)&t, 1) > 0))
6935  return SOAP_OK;
6936  }
6937  else
6938 #endif
6939  {
6941  && (r & SOAP_TCP_SELECT_SND)
6942  && (!(r & SOAP_TCP_SELECT_RCV)
6943  || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0))
6944  return SOAP_OK;
6945  }
6946  }
6947  else if (r < 0)
6948  {
6951  return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
6952  }
6953  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_poll: other end down on socket=%d select=%d\n", (int)soap->socket, r));
6954  return SOAP_EOF;
6955 #else
6956  (void)soap;
6957  return SOAP_OK;
6958 #endif
6959 }
6960 #endif
6961 
6962 /******************************************************************************/
6963 
6964 #ifndef WITH_NOIO
6965 SOAP_FMAC1
6966 int
6967 SOAP_FMAC2
6969 {
6970 #ifndef WITH_LEAN
6971  int r;
6972  if (!soap_valid_socket(soap->socket))
6973  return SOAP_OK; /* OK when no socket! */
6975  if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
6976  r = -1;
6977  if (r < 0 && soap_socket_errno != SOAP_EINTR)
6978  return soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_ready()", SOAP_TCP_ERROR);
6979  if (r > 0)
6980  {
6981  char t;
6982 #ifdef WITH_OPENSSL
6983  if ((soap->imode & SOAP_ENC_SSL) && soap->ssl)
6984  {
6985  if (SSL_peek(soap->ssl, &t, 1) > 0)
6986  return SOAP_OK;
6987  }
6988  else
6989 #endif
6990  {
6991  if (recv(soap->socket, &t, 1, MSG_PEEK) > 0)
6992  return SOAP_OK;
6993  }
6994  }
6995  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "soap_ready: other end not ready to send on socket=%d select=%d\n", (int)soap->socket, r));
6996  return SOAP_EOF;
6997 #else
6998  (void)soap;
6999  return SOAP_OK;
7000 #endif
7001 }
7002 #endif
7003 /******************************************************************************/
7004 
7005 #ifndef WITH_NOIO
7006 SOAP_FMAC1
7008 SOAP_FMAC2
7010 {
7011  int n = (int)sizeof(soap->peer);
7012  int err;
7013 #ifndef WITH_LEAN
7014  int set = 1;
7015 #endif
7016  soap->error = SOAP_OK;
7017  memset((void*)&soap->peer, 0, sizeof(soap->peer));
7019  soap->errmode = 0;
7021  soap->errnum = 0;
7022  soap->keep_alive = 0;
7023  if (!soap_valid_socket(soap->master))
7024  {
7025  soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
7026  return SOAP_INVALID_SOCKET;
7027  }
7028 #ifndef WITH_LEAN
7029  if ((soap->omode & SOAP_IO_UDP))
7030  return soap->socket = soap->master;
7031 #endif
7032  for (;;)
7033  {
7034  if (soap->accept_timeout)
7035  {
7036  for (;;)
7037  {
7038  int r;
7040  if (r > 0)
7041  break;
7042  if (!r)
7043  {
7044  soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
7045  return SOAP_INVALID_SOCKET;
7046  }
7047  if (r < 0)
7048  {
7049  r = soap->errnum;
7050  if (r != SOAP_EINTR)
7051  {
7053  soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
7054  return SOAP_INVALID_SOCKET;
7055  }
7056  }
7057  }
7058  }
7059  n = (int)sizeof(soap->peer);
7060  soap->socket = soap->faccept(soap, soap->master, &soap->peer.addr, &n);
7061  soap->peerlen = (size_t)n;
7063  {
7064 #ifdef WITH_IPV6
7065  char port[16];
7066  struct addrinfo *res = NULL;
7067  struct addrinfo hints;
7068  memset(&hints, 0, sizeof(struct addrinfo));
7069  hints.ai_family = PF_UNSPEC;
7070  hints.ai_socktype = SOCK_STREAM;
7071  hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
7072  getnameinfo(&soap->peer.addr, n, soap->host, sizeof(soap->host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
7073  soap->ip = 0;
7074  soap->ip6[0] = 0;
7075  soap->ip6[1] = 0;
7076  soap->ip6[2] = 0;
7077  soap->ip6[3] = 0;
7078  if (getaddrinfo(soap->host, NULL, &hints, &res) == 0 && res)
7079  {
7080  struct sockaddr_storage result;
7081  memset((void*)&result, 0, sizeof(result));
7082  (void)soap_memcpy(&result, sizeof(result), res->ai_addr, res->ai_addrlen);
7083  freeaddrinfo(res);
7084  if (result.ss_family == AF_INET6)
7085  {
7086  struct sockaddr_in6 *addr = (struct sockaddr_in6*)&result;
7087  struct in6_addr *inaddr = &addr->sin6_addr;
7088  int i;
7089  for (i = 0; i < 16; i++)
7090  soap->ip6[i/4] = (soap->ip6[i/4] << 8) + inaddr->s6_addr[i];
7091  }
7092  else if (result.ss_family == AF_INET)
7093  {
7094  struct sockaddr_in *addr = (struct sockaddr_in*)&result;
7095  soap->ip = ntohl(addr->sin_addr.s_addr);
7096  soap->ip6[2] = 0xFFFF;
7097  soap->ip6[3] = soap->ip;
7098  }
7099  }
7100  soap->port = soap_strtol(port, NULL, 10);
7101 #else
7102  soap->ip = ntohl(soap->peer.in.sin_addr.s_addr);
7103  soap->ip6[0] = 0;
7104  soap->ip6[1] = 0;
7105  soap->ip6[2] = 0xFFFF;
7106  soap->ip6[3] = soap->ip;
7107  (SOAP_SNPRINTF(soap->host, sizeof(soap->host), 80), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
7108  soap->port = (int)ntohs(soap->peer.in.sin_port); /* does not return port number on some systems */
7109 #endif
7110  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", (int)soap->socket, soap->port, soap->host));
7111 #ifndef WITH_LEAN
7112  if ((soap->accept_flags & SO_LINGER))
7113  {
7114  struct linger linger;
7115  memset((void*)&linger, 0, sizeof(linger));
7116  linger.l_onoff = 1;
7117  linger.l_linger = soap->linger_time;
7118  if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
7119  {
7121  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
7123  return SOAP_INVALID_SOCKET;
7124  }
7125  }
7126  if ((soap->accept_flags & ~SO_LINGER) && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int)))
7127  {
7129  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
7131  return SOAP_INVALID_SOCKET;
7132  }
7133 #ifndef UNDER_CE
7134  if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
7135  {
7137  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
7139  return SOAP_INVALID_SOCKET;
7140  }
7141  if (soap->sndbuf > 0 && setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&soap->sndbuf, sizeof(int)))
7142  {
7144  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
7146  return SOAP_INVALID_SOCKET;
7147  }
7148  if (soap->rcvbuf > 0 && setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&soap->rcvbuf, sizeof(int)))
7149  {
7151  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
7153  return SOAP_INVALID_SOCKET;
7154  }
7155 #ifdef TCP_NODELAY
7156  if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
7157  {
7159  soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
7161  return SOAP_INVALID_SOCKET;
7162  }
7163 #endif
7164 #endif
7165 #endif
7166  soap->keep_alive = -(((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
7169  else
7171  return soap->socket;
7172  }
7173  err = soap_socket_errno;
7174  if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
7175  {
7176  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
7177  soap->errnum = err;
7178  soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
7180  return SOAP_INVALID_SOCKET;
7181  }
7182  }
7183 }
7184 #endif
7185 
7186 /******************************************************************************/
7187 
7188 SOAP_FMAC1
7189 int
7190 SOAP_FMAC2
7192 {
7193  int status = soap->error;
7194  int err = SOAP_OK;
7195  soap->part = SOAP_END;
7196 #ifndef WITH_LEANER
7197  if (status && status < 200) /* attachment state is not to be trusted */
7198  {
7199  soap->mime.first = NULL;
7200  soap->mime.last = NULL;
7201  soap->dime.first = NULL;
7202  soap->dime.last = NULL;
7203  }
7204 #endif
7205  if (soap->fdisconnect)
7206  err = soap->fdisconnect(soap);
7207  if (err || status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
7208  {
7209  soap->keep_alive = 0;
7210  if (soap->fclose && (soap->error = soap->fclose(soap)) != SOAP_OK)
7211  return soap->error;
7212  if (err)
7213  return soap->error = err;
7214  }
7215 #ifdef WITH_ZLIB
7216  if (!(soap->mode & SOAP_MIME_POSTCHECK))
7217  {
7220  else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
7223  }
7224 #endif
7225  return soap->error = status;
7226 }
7227 
7228 /******************************************************************************/
7229 
7230 SOAP_FMAC1
7231 int
7232 SOAP_FMAC2
7234 {
7235  soap->keep_alive = 0;
7237  {
7240  }
7241  return soap->error;
7242 }
7243 
7244 /******************************************************************************/
7245 
7246 #ifdef WITH_SELF_PIPE
7247 SOAP_FMAC1
7248 void
7249 SOAP_FMAC2
7250 soap_close_connection(struct soap *soap)
7251 {
7253  write(soap->pipe_fd[1], "1", 1);
7254 }
7255 #endif
7256 
7257 /******************************************************************************/
7258 
7259 #ifndef WITH_NOIO
7260 SOAP_FMAC1
7261 void
7262 SOAP_FMAC2
7264 {
7265  soap_done(soap);
7266 #ifdef WIN32
7267  if (!tcp_done)
7268  return;
7269  tcp_done = 0;
7270  WSACleanup();
7271 #endif
7272 }
7273 #endif
7274 
7275 /******************************************************************************/
7276 
7277 SOAP_FMAC1
7278 void
7279 SOAP_FMAC2
7281 {
7282 #ifdef SOAP_DEBUG
7283  int i;
7284 #endif
7285  if (soap_check_state(soap))
7286  return;
7287  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : ""));
7289 #ifdef SOAP_DEBUG
7290  if (soap->clist)
7291  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Warning: managed C++ data was not deallocated with soap_destroy() from the heap managed by context %p\n", (void*)soap));
7292  if (soap->alist)
7293  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Warning: managed C data was not deallocated with soap_end() from the heap managed by context %p\n", (void*)soap));
7294 #endif
7295  soap->alist = NULL;
7296  while (soap->clist)
7297  {
7298  struct soap_clist *p = soap->clist->next;
7299  SOAP_FREE(soap, soap->clist);
7300  soap->clist = p;
7301  }
7302  if (soap->state == SOAP_INIT)
7303  soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
7304  soap->keep_alive = 0; /* to force close the socket */
7305  if (soap->master == soap->socket) /* do not close twice */
7308 #ifdef WITH_COOKIES
7309  soap_free_cookies(soap);
7310 #endif
7311  while (soap->plugins)
7312  {
7313  struct soap_plugin *p = soap->plugins->next;
7314  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
7315  if (soap->plugins->fcopy || soap->state == SOAP_INIT)
7318  soap->plugins = p;
7319  }
7320  soap->fplugin = fplugin;
7321 #ifndef WITH_NOHTTP
7322  soap->fpost = http_post;
7323  soap->fget = http_get;
7324  soap->fput = http_put;
7325  soap->fpatch = http_patch;
7326  soap->fdel = http_del;
7327  soap->fopt = http_200;
7328  soap->fhead = http_200;
7329  soap->fform = NULL;
7332  soap->fparse = http_parse;
7334 #endif
7335  soap->fheader = NULL;
7336 #ifndef WITH_NOIO
7337 #ifndef WITH_IPV6
7339 #else
7340  soap->fresolve = NULL;
7341 #endif
7342  soap->faccept = tcp_accept;
7343  soap->fopen = tcp_connect;
7347  soap->fsend = fsend;
7348  soap->frecv = frecv;
7349  soap->fpoll = soap_poll;
7350 #else
7351  soap->fopen = NULL;
7352  soap->fclose = NULL;
7353  soap->fpoll = NULL;
7354 #endif
7355 #ifndef WITH_LEANER
7356  soap->fsvalidate = NULL;
7357  soap->fwvalidate = NULL;
7358  soap->feltbegin = NULL;
7359  soap->feltendin = NULL;
7360  soap->feltbegout = NULL;
7361  soap->feltendout = NULL;
7364  soap->fpreparesend = NULL;
7365  soap->fpreparerecv = NULL;
7368  soap->ffiltersend = NULL;
7369  soap->ffilterrecv = NULL;
7370 #endif
7371  soap->fseterror = NULL;
7372  soap->fignore = NULL;
7373  soap->fserveloop = NULL;
7374 #ifdef WITH_OPENSSL
7375  if (soap->session)
7376  {
7377  SSL_SESSION_free(soap->session);
7378  soap->session = NULL;
7379  }
7380 #endif
7381  if (soap->state == SOAP_INIT)
7382  {
7384  {
7387  }
7388  }
7389 #ifdef WITH_OPENSSL
7390  if (soap->ssl)
7391  {
7392  SSL_free(soap->ssl);
7393  soap->ssl = NULL;
7394  }
7395  if (soap->state == SOAP_INIT)
7396  {
7397  if (soap->ctx)
7398  {
7399  SSL_CTX_free(soap->ctx);
7400  soap->ctx = NULL;
7401  }
7402  }
7403  ERR_clear_error();
7404 # if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
7405  /* OpenSSL libraries handle thread init and deinit */
7406 # elif OPENSSL_VERSION_NUMBER >= 0x10000000L
7407  ERR_remove_thread_state(NULL);
7408 # else
7409  ERR_remove_state(0);
7410 # endif
7411 #endif
7412 #ifdef WITH_GNUTLS
7413  if (soap->state == SOAP_INIT)
7414  {
7415  if (soap->xcred)
7416  {
7417  gnutls_certificate_free_credentials(soap->xcred);
7418  soap->xcred = NULL;
7419  }
7420  if (soap->acred)
7421  {
7422  gnutls_anon_free_client_credentials(soap->acred);
7423  soap->acred = NULL;
7424  }
7425  if (soap->cache)
7426  {
7427  gnutls_priority_deinit(soap->cache);
7428  soap->cache = NULL;
7429  }
7430  if (soap->dh_params)
7431  {
7432  gnutls_dh_params_deinit(soap->dh_params);
7433  soap->dh_params = NULL;
7434  }
7435 # if GNUTLS_VERSION_NUMBER < 0x030300
7436  if (soap->rsa_params)
7437  {
7438  gnutls_rsa_params_deinit(soap->rsa_params);
7439  soap->rsa_params = NULL;
7440  }
7441 #endif
7442  }
7443  if (soap->session)
7444  {
7445  gnutls_deinit(soap->session);
7446  soap->session = NULL;
7447  }
7448 #endif
7449 #ifdef WITH_SYSTEMSSL
7450  if (soap->ssl)
7451  gsk_secure_socket_close(&soap->ssl);
7452  if (soap->state == SOAP_INIT)
7453  if (soap->ctx)
7454  gsk_environment_close(&soap->ctx);
7455 #endif
7456 #ifdef WITH_C_LOCALE
7457  SOAP_FREELOCALE(soap);
7458 #endif
7459 #ifdef WITH_ZLIB
7460  if (soap->d_stream)
7461  {
7463  soap->d_stream = NULL;
7464  }
7465  if (soap->z_buf)
7466  {
7467  SOAP_FREE(soap, soap->z_buf);
7468  soap->z_buf = NULL;
7469  }
7470 #endif
7471 #ifdef SOAP_DEBUG
7472  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
7473  for (i = 0; i < SOAP_MAXLOGS; i++)
7474  {
7475  soap_close_logfile(soap, i);
7476  if (soap->logfile[i])
7477  {
7479  soap->logfile[i] = NULL;
7480  }
7481  }
7482 #endif
7483 #ifdef WITH_SELF_PIPE
7484  close(soap->pipe_fd[0]);
7485  close(soap->pipe_fd[1]);
7486 #endif
7487 #ifdef SOAP_MEM_DEBUG
7488  soap_free_mht(soap);
7489 #endif
7490  soap->state = SOAP_NONE;
7491 }
7492 
7493 /******************************************************************************\
7494  *
7495  * HTTP
7496  *
7497 \******************************************************************************/
7498 
7499 #ifndef WITH_NOHTTP
7500 static int
7502 {
7503  char header[SOAP_HDRLEN], *s;
7504  int err = SOAP_OK;
7505  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
7506  soap->fform = NULL;
7507  *soap->endpoint = '\0';
7508  soap->bearer = NULL;
7509 #ifdef WITH_NTLM
7510  if (!soap->ntlm_challenge)
7511 #endif
7512  {
7513  soap->userid = NULL;
7514  soap->passwd = NULL;
7515  soap->authrealm = NULL;
7516  }
7517 #ifdef WITH_NTLM
7519 #endif
7520  soap->proxy_from = NULL;
7521  soap->cors_origin = NULL;
7522  soap->cors_method = NULL;
7523  soap->cors_header = NULL;
7524  do
7525  {
7526  soap->length = 0;
7527  soap->http_content = NULL;
7528  soap->action = NULL;
7529  soap->status = 0;
7530  soap->body = 1;
7531  if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
7532  {
7533  if (soap->error == SOAP_EOF)
7534  return SOAP_EOF;
7535  return soap->error = 414;
7536  }
7537  s = strchr(soap->msgbuf, ' ');
7538  if (s)
7539  {
7540  soap->status = (unsigned short)soap_strtoul(s, &s, 10);
7541  if (!soap_coblank((soap_wchar)*s))
7542  soap->status = 0;
7543  }
7544  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
7545  for (;;)
7546  {
7547  if (soap_getline(soap, header, SOAP_HDRLEN))
7548  {
7549  if (soap->error == SOAP_EOF)
7550  {
7551  soap->error = SOAP_OK;
7552  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "EOF in HTTP header, try to continue anyway\n"));
7553  break;
7554  }
7555  return soap->error;
7556  }
7557  if (!*header)
7558  break;
7559  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
7560  s = strchr(header, ':');
7561  if (s)
7562  {
7563  char *t;
7564  *s = '\0';
7565  do
7566  {
7567  s++;
7568  } while (*s && *s <= 32);
7569  if (*s == '"')
7570  s++;
7571  t = s + strlen(s) - 1;
7572  while (t > s && *t <= 32)
7573  t--;
7574  if (t >= s && *t == '"')
7575  t--;
7576  t[1] = '\0';
7577  soap->error = soap->fparsehdr(soap, header, s);
7578  if (soap->error)
7579  {
7580  if (soap->error < SOAP_STOP)
7581  return soap->error;
7582  err = soap->error;
7583  soap->error = SOAP_OK;
7584  }
7585  }
7586  }
7587  } while (soap->status == 100);
7588  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
7589  s = strstr(soap->msgbuf, "HTTP/");
7590  if (s && s[5] == '1' && s[6] == '.' && s[7] == '0')
7591  {
7592  soap->keep_alive = 0; /* HTTP 1.0 does not support keep-alive */
7593  if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
7594  soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */
7595  }
7596  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
7597  if (soap->status == 0)
7598  {
7599  size_t l = 0;
7600  if (s)
7601  {
7602  if (!strncmp(soap->msgbuf, "POST ", l = 5))
7603  soap->status = SOAP_POST;
7604  else if (!strncmp(soap->msgbuf, "GET ", l = 4))
7605  soap->status = SOAP_GET;
7606  else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
7607  soap->status = SOAP_PUT;
7608  else if (!strncmp(soap->msgbuf, "PATCH ", l = 4))
7609  soap->status = SOAP_PATCH;
7610  else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
7611  soap->status = SOAP_DEL;
7612  else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
7613  soap->status = SOAP_HEAD;
7614  else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8))
7616  }
7617  if (s && soap->status)
7618  {
7619  size_t m, n, k;
7620  int r;
7621  while (soap->msgbuf[l] && soap_coblank((soap_wchar)soap->msgbuf[l]))
7622  l++;
7623  m = strlen(soap->endpoint);
7624  n = m + (s - soap->msgbuf) - l - 1;
7625  if (n >= sizeof(soap->endpoint))
7626  n = sizeof(soap->endpoint) - 1;
7627  if (m > n)
7628  m = n;
7629  k = n - m + 1;
7630  if (k >= sizeof(soap->path))
7631  k = sizeof(soap->path) - 1;
7632  while (k > 0 && soap_coblank((soap_wchar)soap->msgbuf[l + k - 1]))
7633  k--;
7634  if (soap_strncpy(soap->path, sizeof(soap->path), soap->msgbuf + l, k))
7635  return soap->error = 414;
7636  if (*soap->path && *soap->path != '/')
7637  r = soap_strncpy(soap->endpoint, sizeof(soap->endpoint), soap->path, k);
7638  else
7639  r = soap_strncat(soap->endpoint, sizeof(soap->endpoint), soap->path, k);
7640  if (r)
7641  return soap->error = 414;
7642  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Target endpoint='%s' path='%s'\n", soap->endpoint, soap->path));
7643  if (err)
7644  return soap->error = err;
7645  }
7646  else if (err)
7647  {
7648  return soap->error = err;
7649  }
7650  else if (s)
7651  {
7652  return soap->error = 405;
7653  }
7654  return SOAP_OK;
7655  }
7656  if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */
7657  || soap->status == 400 /* Bad Request */
7658  || soap->status == 500) /* Internal Server Error */
7659  return soap->error = SOAP_OK;
7660  return soap->error = soap->status;
7661 }
7662 #endif
7663 
7664 /******************************************************************************/
7665 
7666 #ifndef WITH_NOHTTP
7667 static int
7668 http_parse_header(struct soap *soap, const char *key, const char *val)
7669 {
7670  if (!soap_tag_cmp(key, "Host"))
7671  {
7672 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
7673  if ((soap->imode & SOAP_ENC_SSL))
7674  soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "https://");
7675  else
7676 #endif
7677  soap_strcpy(soap->endpoint, sizeof(soap->endpoint), "http://");
7678  if (soap_strncat(soap->endpoint, sizeof(soap->endpoint), val, sizeof(soap->endpoint) - 9))
7679  return soap->error = SOAP_HDR;
7680  }
7681 #ifndef WITH_LEANER
7682  else if (!soap_tag_cmp(key, "Content-Type"))
7683  {
7684  const char *action;
7685  soap->http_content = soap_strdup(soap, val);
7686  if (soap_http_header_attribute(soap, val, "application/dime"))
7687  soap->imode |= SOAP_ENC_DIME;
7688  else if (soap_http_header_attribute(soap, val, "multipart/related")
7689  || soap_http_header_attribute(soap, val, "multipart/form-data"))
7690  {
7691  const char *type;
7694  soap->imode |= SOAP_ENC_MIME;
7695  type = soap_http_header_attribute(soap, val, "type");
7696  if (type && !strcmp(type, "application/xop+xml"))
7697  soap->imode |= SOAP_ENC_MTOM;
7698  }
7699  action = soap_http_header_attribute(soap, val, "action");
7700  if (action)
7701  {
7702  if (*action == '"')
7703  {
7704  soap->action = soap_strdup(soap, action + 1);
7705  if (soap->action && *soap->action)
7706  soap->action[strlen(soap->action) - 1] = '\0';
7707  }
7708  else
7709  soap->action = soap_strdup(soap, action);
7710  }
7711  }
7712 #endif
7713  else if (!soap_tag_cmp(key, "Content-Length"))
7714  {
7715  soap->length = soap_strtoull(val, NULL, 10);
7716  if (soap->length == 0)
7717  soap->body = 0;
7718  }
7719  else if (!soap_tag_cmp(key, "Content-Encoding"))
7720  {
7721  if (!soap_tag_cmp(val, "deflate"))
7722 #ifdef WITH_ZLIB
7724 #else
7725  return SOAP_ZLIB_ERROR;
7726 #endif
7727  else if (!soap_tag_cmp(val, "gzip"))
7728 #ifdef WITH_GZIP
7730 #else
7731  return SOAP_ZLIB_ERROR;
7732 #endif
7733  }
7734 #ifdef WITH_ZLIB
7735  else if (!soap_tag_cmp(key, "Accept-Encoding"))
7736  {
7737 #ifdef WITH_GZIP
7738  if (strchr(val, '*') || soap_http_header_attribute(soap, val, "gzip"))
7740  else
7741 #endif
7742  if (strchr(val, '*') || soap_http_header_attribute(soap, val, "deflate"))
7744  else
7746  }
7747 #endif
7748  else if (!soap_tag_cmp(key, "Transfer-Encoding"))
7749  {
7750  soap->imode &= ~SOAP_IO;
7751  if (!soap_tag_cmp(val, "chunked"))
7752  soap->imode |= SOAP_IO_CHUNK;
7753  }
7754  else if (!soap_tag_cmp(key, "Connection"))
7755  {
7756  if (!soap_tag_cmp(val, "close"))
7757  soap->keep_alive = 0;
7758  }
7759 #if !defined(WITH_LEAN) || defined(WITH_NTLM)
7760  else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization"))
7761  {
7762 #ifdef WITH_NTLM
7763  if (!soap_tag_cmp(val, "NTLM*"))
7764  {
7765  soap->ntlm_challenge = soap_strdup(soap, val + 4);
7766  }
7767  else
7768 #endif
7769  if (!soap_tag_cmp(val, "Bearer *"))
7770  {
7771  soap->bearer = soap_strdup(soap, val + 7);
7772  }
7773  else if (!soap_tag_cmp(val, "Basic *"))
7774  {
7775  int n;
7776  char *s;
7777  soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
7778  soap->tmpbuf[n] = '\0';
7779  s = strchr(soap->tmpbuf, ':');
7780  if (s)
7781  {
7782  *s = '\0';
7784  soap->passwd = soap_strdup(soap, s + 1);
7785  }
7786  }
7787  }
7788  else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate"))
7789  {
7790 #ifdef WITH_NTLM
7791  if (!soap_tag_cmp(val, "NTLM*"))
7792  soap->ntlm_challenge = soap_strdup(soap, val + 4);
7793  else
7794 #endif
7796  }
7797  else if (!soap_tag_cmp(key, "Expect"))
7798  {
7799  if (!soap_tag_cmp(val, "100-continue"))
7800  {
7801  if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) != SOAP_OK
7802  || (soap->error = soap->fposthdr(soap, NULL, NULL)) != SOAP_OK)
7803  return soap->error;
7804  }
7805  }
7806 #endif
7807  else if (!soap_tag_cmp(key, "SOAPAction"))
7808  {
7809  if (*val == '"')
7810  {
7811  soap->action = soap_strdup(soap, val + 1);
7812  if (*soap->action)
7813  soap->action[strlen(soap->action) - 1] = '\0';
7814  }
7815  else
7816  soap->action = soap_strdup(soap, val);
7817  }
7818  else if (!soap_tag_cmp(key, "Location"))
7819  {
7820  soap_strcpy(soap->endpoint, sizeof(soap->endpoint), val);
7821  }
7822  else if (!soap_tag_cmp(key, "X-Forwarded-For"))
7823  {
7824  soap->proxy_from = soap_strdup(soap, val);
7825  }
7826  else if (!soap_tag_cmp(key, "Origin"))
7827  {
7828  soap->origin = soap_strdup(soap, val);
7830  }
7831  else if (!soap_tag_cmp(key, "Access-Control-Request-Method"))
7832  {
7833  soap->cors_method = soap_strdup(soap, val);
7834  }
7835  else if (!soap_tag_cmp(key, "Access-Control-Request-Headers"))
7836  {
7837  soap->cors_header = soap_strdup(soap, val);
7838  }
7839 #ifdef WITH_COOKIES
7840  else if (!soap_tag_cmp(key, "Cookie")
7841  || !soap_tag_cmp(key, "Cookie2")
7842  || !soap_tag_cmp(key, "Set-Cookie")
7843  || !soap_tag_cmp(key, "Set-Cookie2"))
7844  {
7845  soap_getcookies(soap, val);
7846  }
7847 #endif
7848  return SOAP_OK;
7849 }
7850 #endif
7851 
7852 /******************************************************************************/
7853 
7854 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
7855 SOAP_FMAC1
7856 const char*
7857 SOAP_FMAC2
7858 soap_http_header_attribute(struct soap *soap, const char *line, const char *key)
7859 {
7860  const char *s = line;
7861  if (s)
7862  {
7863  while (*s)
7864  {
7865  short flag;
7866  s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
7867  flag = soap_tag_cmp(soap->tmpbuf, key);
7868  s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
7869  if (!flag)
7870  return soap->tmpbuf;
7871  }
7872  }
7873  return NULL;
7874 }
7875 #endif
7876 
7877 /******************************************************************************/
7878 
7879 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
7880 SOAP_FMAC1
7881 const char*
7882 SOAP_FMAC2
7883 soap_decode_key(char *buf, size_t len, const char *val)
7884 {
7885  return soap_decode(buf, len, val, "=,;");
7886 }
7887 #endif
7888 
7889 /******************************************************************************/
7890 
7891 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
7892 SOAP_FMAC1
7893 const char*
7894 SOAP_FMAC2
7895 soap_decode_val(char *buf, size_t len, const char *val)
7896 {
7897  if (*val != '=')
7898  {
7899  *buf = '\0';
7900  return val;
7901  }
7902  return soap_decode(buf, len, val + 1, ",;");
7903 }
7904 #endif
7905 
7906 /******************************************************************************/
7907 
7908 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
7909 static const char *
7910 soap_decode(char *buf, size_t len, const char *val, const char *sep)
7911 {
7912  const char *s;
7913  char *t = buf;
7914  size_t i = len;
7915  for (s = val; *s; s++)
7916  if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
7917  break;
7918  if (len > 0)
7919  {
7920  if (*s == '"')
7921  {
7922  s++;
7923  while (*s && *s != '"' && --i)
7924  *t++ = *s++;
7925  }
7926  else
7927  {
7928  while (*s && !strchr(sep, *s) && --i)
7929  {
7930  if (*s == '%' && s[1] && s[2])
7931  {
7932  *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
7933  + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
7934  s += 3;
7935  }
7936  else
7937  *t++ = *s++;
7938  }
7939  }
7940  buf[len - 1] = '\0'; /* appease static checkers that get confused */
7941  }
7942  *t = '\0';
7943  while (*s && !strchr(sep, *s))
7944  s++;
7945  return s;
7946 }
7947 #endif
7948 
7949 /******************************************************************************/
7950 
7951 #ifndef WITH_NOHTTP
7952 static const char*
7953 http_error(struct soap *soap, int status)
7954 {
7955  const char *msg = SOAP_STR_EOS;
7956  (void)soap;
7957  (void)status;
7958 #ifndef WITH_LEAN
7959  msg = soap_code_str(h_http_error_codes, status);
7960  if (!msg)
7961  msg = SOAP_STR_EOS;
7962 #endif
7963  return msg;
7964 }
7965 #endif
7966 
7967 /******************************************************************************/
7968 
7969 #ifndef WITH_NOHTTP
7970 static int
7972 {
7973  (void)soap;
7974  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n"));
7975  return SOAP_GET_METHOD;
7976 }
7977 #endif
7978 
7979 /******************************************************************************/
7980 
7981 #ifndef WITH_NOHTTP
7982 static int
7984 {
7985  (void)soap;
7986  return SOAP_PUT_METHOD;
7987 }
7988 #endif
7989 
7990 /******************************************************************************/
7991 
7992 #ifndef WITH_NOHTTP
7993 static int
7995 {
7996  (void)soap;
7997  return SOAP_PATCH_METHOD;
7998 }
7999 #endif
8000 /******************************************************************************/
8001 
8002 #ifndef WITH_NOHTTP
8003 static int
8005 {
8006  (void)soap;
8007  return SOAP_DEL_METHOD;
8008 }
8009 #endif
8010 /******************************************************************************/
8011 
8012 #ifndef WITH_NOHTTP
8013 static int
8015 {
8016  if (soap->origin && soap->cors_method) /* CORS Origin and Access-Control-Request-Method headers */
8017  {
8018  soap->cors_origin = soap->cors_allow; /* modify this code or hook your own soap->fopt() callback with logic */
8019  soap->cors_methods = "GET, PUT, PATCH, POST, HEAD, OPTIONS";
8021  }
8022  return soap_send_empty_response(soap, 200);
8023 }
8024 #endif
8025 
8026 /******************************************************************************/
8027 
8028 #ifndef WITH_NOHTTP
8029 static int
8030 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, ULONG64 count)
8031 {
8032  const char *s;
8033  int err;
8034  size_t l;
8035  switch (soap->status)
8036  {
8037  case SOAP_GET:
8038  s = "GET";
8039  break;
8040  case SOAP_PUT:
8041  s = "PUT";
8042  break;
8043  case SOAP_PATCH:
8044  s = "PATCH";
8045  break;
8046  case SOAP_DEL:
8047  s = "DELETE";
8048  break;
8049  case SOAP_CONNECT:
8050  s = "CONNECT";
8051  break;
8052  case SOAP_HEAD:
8053  s = "HEAD";
8054  break;
8055  case SOAP_OPTIONS:
8056  s = "OPTIONS";
8057  break;
8058  default:
8059  s = "POST";
8060  }
8061  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)"));
8062  if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && soap_tag_cmp(endpoint, "httpg:*")))
8063  return SOAP_OK;
8064  /* set l to prevent overruns ('host' and 'soap->host' are substrings of 'endpoint') */
8065  l = strlen(endpoint) + strlen(soap->http_version) + 80;
8066  if (l > sizeof(soap->tmpbuf))
8067  return soap->error = SOAP_EOM;
8068  if (soap->status == SOAP_CONNECT)
8069  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
8070  else if (soap->proxy_host && endpoint)
8071  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s %s HTTP/%s", s, endpoint, soap->http_version);
8072  else
8073  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
8074  err = soap->fposthdr(soap, soap->tmpbuf, NULL);
8075  if (err)
8076  return err;
8077 #ifdef WITH_OPENSSL
8078  if ((soap->ssl && port != 443) || (!soap->ssl && port != 80))
8079 #else
8080  if (port != 80)
8081 #endif
8082  {
8083 #ifdef WITH_IPV6
8084  if (*host != '[' && strchr(host, ':'))
8085  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]:%d", host, port); /* RFC 2732 */
8086  else
8087 #endif
8088  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "%s:%d", host, port);
8089  }
8090  else
8091  {
8092 #ifdef WITH_IPV6
8093  if (*host != '[' && strchr(host, ':'))
8094  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l), "[%s]", host); /* RFC 2732 */
8095  else
8096 #endif
8097  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), host);
8098  }
8099  err = soap->fposthdr(soap, "Host", soap->tmpbuf);
8100  if (err)
8101  return err;
8102  err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8");
8103  if (err)
8104  return err;
8105  if (soap->origin)
8106  {
8107  err = soap->fposthdr(soap, "Origin", soap->origin);
8108  if (err)
8109  return err;
8110  if (soap->status == SOAP_OPTIONS)
8111  {
8112  err = soap->fposthdr(soap, "Access-Control-Request-Method", soap->cors_method ? soap->cors_method : "POST");
8113  if (err)
8114  return err;
8115  if (soap->cors_header)
8116  {
8117  err = soap->fposthdr(soap, "Access-Control-Request-Headers", soap->cors_header);
8118  if (err)
8119  return err;
8120  }
8121  }
8122  }
8123  err = soap_puthttphdr(soap, SOAP_OK, count);
8124  if (err)
8125  return err;
8126 #ifndef WITH_LEANER
8127  if ((soap->imode & SOAP_ENC_MTOM))
8128  {
8129  err = soap->fposthdr(soap, "Accept", "multipart/related,application/xop+xml,*/*;q=0.8");
8130  if (err)
8131  return err;
8132  }
8133 #endif
8134 #ifdef WITH_ZLIB
8135 #ifdef WITH_GZIP
8136  err = soap->fposthdr(soap, "Accept-Encoding", "gzip,deflate");
8137 #else
8138  err = soap->fposthdr(soap, "Accept-Encoding", "deflate");
8139 #endif
8140  if (err)
8141  return err;
8142 #endif
8143 #if !defined(WITH_LEAN) || defined(WITH_NTLM)
8144  if (soap->bearer)
8145  {
8146  l = strlen(soap->bearer);
8147  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 1), "Bearer %s", soap->bearer);
8148  err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
8149  if (err)
8150  return err;
8151  }
8152 #ifdef WITH_NTLM
8153  if (soap->ntlm_challenge)
8154  {
8155  l = strlen(soap->ntlm_challenge);
8156  if (l)
8157  {
8158  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), l + 5), "NTLM %s", soap->ntlm_challenge);
8159  if (soap->proxy_host)
8160  {
8161  err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf);
8162  if (err)
8163  return err;
8164  }
8165  else
8166  {
8167  err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
8168  if (err)
8169  return err;
8170  }
8171  }
8172  }
8173  else
8174  {
8175 #endif
8176  if (soap->userid && soap->passwd)
8177  {
8178  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic ");
8179  (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, strlen(soap->userid) + strlen(soap->passwd) + 1), "%s:%s", soap->userid, soap->passwd);
8180  soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
8181  err = soap->fposthdr(soap, "Authorization", soap->tmpbuf);
8182  if (err)
8183  return err;
8184  }
8186  {
8187  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic ");
8188  (SOAP_SNPRINTF(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) + 1), "%s:%s", soap->proxy_userid, soap->proxy_passwd);
8189  soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
8190  err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf);
8191  if (err)
8192  return err;
8193  }
8194 #ifdef WITH_NTLM
8195  }
8196 #endif
8197 #endif
8198 #ifdef WITH_COOKIES
8199 #ifdef WITH_OPENSSL
8200  if (soap_putcookies(soap, host, path, soap->ssl != NULL))
8201  return soap->error;
8202 #else
8203  if (soap_putcookies(soap, host, path, 0))
8204  return soap->error;
8205 #endif
8206 #endif
8207  if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL)
8208  {
8209  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(action) + 2), "\"%s\"", action);
8210  err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf);
8211  if (err)
8212  return err;
8213  }
8214  return soap->fposthdr(soap, NULL, NULL);
8215 }
8216 #endif
8217 
8218 /******************************************************************************/
8219 
8220 #ifndef WITH_NOHTTP
8221 static int
8222 http_send_header(struct soap *soap, const char *s)
8223 {
8224  const char *t;
8225  do
8226  {
8227  t = strchr(s, '\n'); /* disallow \n in HTTP headers */
8228  if (!t)
8229  t = s + strlen(s);
8230  if (soap_send_raw(soap, s, t - s))
8231  return soap->error;
8232  s = t + 1;
8233  } while (*t);
8234  return SOAP_OK;
8235 }
8236 #endif
8237 
8238 /******************************************************************************/
8239 
8240 #ifndef WITH_NOHTTP
8241 static int
8242 http_post_header(struct soap *soap, const char *key, const char *val)
8243 {
8244  if (key)
8245  {
8246  if (http_send_header(soap, key))
8247  return soap->error;
8248  if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
8249  return soap->error;
8250  }
8251  return soap_send_raw(soap, "\r\n", 2);
8252 }
8253 #endif
8254 
8255 /******************************************************************************/
8256 
8257 #ifndef WITH_NOHTTP
8258 static int
8259 http_response(struct soap *soap, int status, ULONG64 count)
8260 {
8261  int err;
8262  char http[32];
8263  int code = status;
8264  const char *line;
8265 #ifdef WMW_RPM_IO
8266  if (soap->rpmreqid)
8267  httpOutputEnable(soap->rpmreqid);
8268  if (soap->rpmreqid
8271  || soap->recvfd != 0
8272  || soap->sendfd != 1
8273  || soap->os) /* RPM behaves as if standalone */
8274 #else
8277 #ifndef UNDER_CE
8278  || soap->recvfd != 0
8279  || soap->sendfd != 1
8280 #else
8281  || soap->recvfd != stdin
8282  || soap->sendfd != stdout
8283 #endif
8284  || soap->os) /* standalone server application (over sockets), not CGI (over stdin/out) */
8285 #endif
8286  (SOAP_SNPRINTF(http, sizeof(http), strlen(soap->http_version) + 5), "HTTP/%s", soap->http_version);
8287  else
8288  soap_strcpy(http, sizeof(http), "Status:");
8289  if (status >= SOAP_FILE && status < SOAP_FILE + 600)
8290  {
8291  code = status - SOAP_FILE;
8292  if (code == 0)
8293  code = 200;
8294  }
8295  else if (!status || status == SOAP_HTML)
8296  {
8297  if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
8298  code = 200;
8299  else
8300  code = 202;
8301  }
8302  else if (status < 200 || status >= 600)
8303  {
8304  const char *s = *soap_faultcode(soap);
8305  if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
8306  code = 405;
8307  else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
8308  code = 400;
8309  else
8310  code = 500;
8311  }
8312  line = http_error(soap, code);
8313  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line));
8314  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(http) + 22 + strlen(line)), "%s %d %s", http, code, line);
8315  err = soap->fposthdr(soap, soap->tmpbuf, NULL);
8316  if (err)
8317  return err;
8318 #ifndef WITH_LEAN
8319  if (status == 401)
8320  {
8321  (SOAP_SNPRINTF_SAFE(soap->tmpbuf, sizeof(soap->tmpbuf)), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) + 14 < sizeof(soap->tmpbuf)) ? soap->authrealm : "gSOAP Web Service");
8322  err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf);
8323  if (err)
8324  return err;
8325  }
8326  else if ((status >= 301 && status <= 303) || status == 307)
8327  {
8328  err = soap->fposthdr(soap, "Location", soap->endpoint);
8329  if (err)
8330  return err;
8331  }
8332 #endif
8333  err = soap->fposthdr(soap, "Server", "gSOAP/2.8");
8334  if (err)
8335  return err;
8336  if (soap->cors_origin)
8337  {
8338  err = soap->fposthdr(soap, "Access-Control-Allow-Origin", soap->cors_origin);
8339  if (err)
8340  return err;
8341  err = soap->fposthdr(soap, "Access-Control-Allow-Credentials", "true");
8342  if (err)
8343  return err;
8344  if (soap->cors_methods)
8345  {
8346  err = soap->fposthdr(soap, "Access-Control-Allow-Methods", soap->cors_methods);
8347  if (err)
8348  return err;
8349  if (soap->cors_headers)
8350  {
8351  err = soap->fposthdr(soap, "Access-Control-Allow-Headers", soap->cors_headers);
8352  if (err)
8353  return err;
8354  }
8355  }
8356  }
8357  if (soap->x_frame_options)
8358  {
8359  err = soap->fposthdr(soap, "X-Frame-Options", soap->x_frame_options);
8360  if (err)
8361  return err;
8362  }
8363  soap->cors_origin = NULL;
8364  soap->cors_methods = NULL;
8365  soap->cors_headers = NULL;
8366  err = soap_puthttphdr(soap, status, count);
8367  if (err)
8368  return err;
8369 #ifdef WITH_COOKIES
8370  if (soap_putsetcookies(soap))
8371  return soap->error;
8372  soap_free_cookies(soap);
8373 #endif
8374  return soap->fposthdr(soap, NULL, NULL);
8375 }
8376 #endif
8377 
8378 /******************************************************************************/
8379 
8380 SOAP_FMAC1
8381 int
8382 SOAP_FMAC2
8383 soap_response(struct soap *soap, int status)
8384 {
8385  ULONG64 count;
8386  if (!(soap->omode & (SOAP_ENC_PLAIN | SOAP_IO_STORE /* this tests for chunking too */))
8387  && (status == SOAP_HTML || (status >= SOAP_FILE && status < SOAP_FILE + 600)))
8389  soap->status = status;
8391  if (soap_init_send(soap))
8392  return soap->error;
8393 #ifndef WITH_NOHTTP
8394  if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN))
8395  {
8396  int k = soap->mode;
8397  soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
8398  if ((k & SOAP_IO) != SOAP_IO_FLUSH)
8399  soap->mode |= SOAP_IO_BUFFER;
8400  soap->error = soap->fresponse(soap, status, count);
8401  if (soap->error)
8402  return soap->error;
8403 #ifndef WITH_LEANER
8404  if ((k & SOAP_IO) == SOAP_IO_CHUNK)
8405  {
8406  if (soap_flush(soap))
8407  return soap->error;
8408  }
8409 #endif
8410  soap->mode = k;
8411  }
8412 #endif
8413 #ifndef WITH_LEANER
8415  return soap->error;
8416 #endif
8417  return SOAP_OK;
8418 }
8419 
8420 /******************************************************************************/
8421 
8422 SOAP_FMAC1
8423 const char*
8424 SOAP_FMAC2
8425 soap_extend_url(struct soap *soap, const char *s, const char *t)
8426 {
8427  if (s)
8428  soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), s);
8429  else
8430  *soap->msgbuf = '\0';
8431  if (t && (*t == '/' || *t == '?'))
8432  {
8433  char *r = strchr(soap->msgbuf, '?');
8434  if (r)
8435  {
8436  if (*t == '?')
8437  {
8438  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
8439  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t + 1);
8440  }
8441  else /* *t == '/' */
8442  {
8443  size_t l = r - soap->msgbuf;
8444  *r = '\0';
8445  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t);
8446  if (s)
8447  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s + l);
8448  }
8449  }
8450  else
8451  {
8452  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), t);
8453  }
8454  }
8455  return soap->msgbuf;
8456 }
8457 
8458 /******************************************************************************/
8459 
8460 SOAP_FMAC1
8461 const char*
8462 SOAP_FMAC2
8463 soap_extend_url_query(struct soap *soap, const char *s, const char *t)
8464 {
8465  (void)soap_extend_url(soap, s, t); /* fills and returns soap->msgbuf */
8466  if (strchr(soap->msgbuf, '?'))
8467  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
8468  else
8469  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "?");
8470  return soap->msgbuf;
8471 }
8472 
8473 /******************************************************************************/
8474 
8475 SOAP_FMAC1
8476 void
8477 SOAP_FMAC2
8478 soap_url_query(struct soap *soap, const char *s, const char *t)
8479 {
8480  size_t n = strlen(s);
8481  if (n)
8482  {
8483  char *r = soap->msgbuf;
8484  size_t k = n - (s[n-1] == '=');
8485  while ((r = strchr(r, '{')) != NULL)
8486  if (!strncmp(++r, s, k) && r[k] == '}')
8487  break;
8488  if (r)
8489  {
8490  size_t m = t ? strlen(t) : 0;
8491  (void)soap_memmove(r + m - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r + n + 1), r + k + 1, strlen(r + k + 1) + 1);
8492  if (m)
8493  (void)soap_memmove(r - 1, soap->msgbuf + sizeof(soap->msgbuf) - (r - 1), t, m);
8494  }
8495  else
8496  {
8497  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), s);
8498  if (t)
8499  {
8500  int m = (int)strlen(soap->msgbuf); /* msgbuf length is max SOAP_TMPLEN or just 1024 bytes */
8501  (void)soap_encode_url(t, soap->msgbuf + m, (int)sizeof(soap->msgbuf) - m);
8502  }
8503  soap_strcat(soap->msgbuf, sizeof(soap->msgbuf), "&");
8504  }
8505  }
8506 }
8507 
8508 /******************************************************************************/
8509 
8510 SOAP_FMAC1
8511 int
8512 SOAP_FMAC2
8513 soap_encode_url(const char *s, char *t, int len)
8514 {
8515  int c;
8516  int n = len;
8517  if (s && n > 0)
8518  {
8519  while ((c = *s++) && --n > 0)
8520  {
8521  if (c == '-'
8522  || c == '.'
8523  || (c >= '0' && c <= '9')
8524  || (c >= 'A' && c <= 'Z')
8525  || c == '_'
8526  || (c >= 'a' && c <= 'z')
8527  || c == '~')
8528  {
8529  *t++ = c;
8530  }
8531  else if (n > 2)
8532  {
8533  *t++ = '%';
8534  *t++ = (c >> 4) + (c > 159 ? '7' : '0');
8535  c &= 0xF;
8536  *t++ = c + (c > 9 ? '7' : '0');
8537  n -= 2;
8538  }
8539  else
8540  {
8541  break;
8542  }
8543  }
8544  *t = '\0';
8545  }
8546  return len - n;
8547 }
8548 
8549 /******************************************************************************/
8550 
8551 SOAP_FMAC1
8552 const char*
8553 SOAP_FMAC2
8554 soap_encode_url_string(struct soap *soap, const char *s)
8555 {
8556  if (s)
8557  {
8558  int n = 3 * (int)strlen(s) + 1;
8559  char *t = (char*)soap_malloc(soap, n);
8560  if (t)
8561  {
8562  (void)soap_encode_url(s, t, n);
8563  return t;
8564  }
8565  }
8566  return SOAP_STR_EOS;
8567 }
8568 
8569 /******************************************************************************\
8570  *
8571  * HTTP Cookies RFC 6265
8572  *
8573 \******************************************************************************/
8574 
8575 #ifdef WITH_COOKIES
8576 
8577 SOAP_FMAC1
8578 struct soap_cookie*
8579 SOAP_FMAC2
8580 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
8581 {
8582  return soap_cookie_env(soap, name, domain, path, 0);
8583 }
8584 
8585 /******************************************************************************/
8586 
8587 SOAP_FMAC1
8588 struct soap_cookie*
8589 SOAP_FMAC2
8590 soap_cookie_env(struct soap *soap, const char *name, const char *domain, const char *path, short env)
8591 {
8592  struct soap_cookie *p;
8593  if (!domain && !env)
8595  if (!path)
8596  path = soap->cookie_path;
8597  if (!path)
8598  path = SOAP_STR_EOS;
8599  else if (*path == '/')
8600  path++;
8601  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s' env=%hd\n", name, domain ? domain : "(null)", path ? path : "(null)", env));
8602  for (p = soap->cookies; p; p = p->next)
8603  {
8604  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s='%s' domain='%s' path='%s' env=%hd\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->env));
8605  if ((!env || p->env)
8606  && !strcmp(p->name, name)
8607  && (!domain || (domain && p->domain && !strcmp(p->domain, domain)))
8608  && (!path || (path && p->path && !strncmp(p->path, path, strlen(p->path)))))
8609  break;
8610  }
8611  return p;
8612 }
8613 
8614 /******************************************************************************/
8615 
8616 SOAP_FMAC1
8617 struct soap_cookie*
8618 SOAP_FMAC2
8619 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
8620 {
8621  struct soap_cookie **p, *q;
8622  int n;
8623  if (!domain)
8625  if (!path)
8626  path = soap->cookie_path;
8627  if (!path)
8628  path = SOAP_STR_EOS;
8629  else if (*path == '/')
8630  path++;
8631  q = soap_cookie(soap, name, domain, path);
8632  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s='%s' domain='%s' path='%s'\n", q ? SOAP_STR_EOS : "new ", name, value ? value : "(null)", domain ? domain : "(null)", path ? path : "(null)"));
8633  if (!q)
8634  {
8635  q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie));
8636  if (q)
8637  {
8638  size_t l = strlen(name) + 1;
8639  q->name = NULL;
8640  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
8641  q->name = (char*)SOAP_MALLOC(soap, l);
8642  if (q->name)
8643  (void)soap_memcpy(q->name, l, name, l);
8644  q->value = NULL;
8645  q->domain = NULL;
8646  q->path = NULL;
8647  q->expire = 0;
8648  q->maxage = -1;
8649  q->version = 1;
8650  q->secure = 0;
8651  q->modified = 0;
8652  for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
8653  if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
8654  break;
8655  if (n)
8656  {
8657  q->next = *p;
8658  *p = q;
8659  }
8660  else
8661  {
8662  if (q->name)
8663  SOAP_FREE(soap, q->name);
8664  SOAP_FREE(soap, q);
8665  q = NULL;
8666  }
8667  }
8668  }
8669  else
8670  {
8671  q->modified = 1;
8672  }
8673  if (q)
8674  {
8675  if (q->value)
8676  {
8677  if (!value || strcmp(value, q->value))
8678  {
8679  SOAP_FREE(soap, q->value);
8680  q->value = NULL;
8681  }
8682  }
8683  if (value && *value && !q->value)
8684  {
8685  size_t l = strlen(value) + 1;
8686  q->value = NULL;
8687  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
8688  q->value = (char*)SOAP_MALLOC(soap, l);
8689  if (q->value)
8690  soap_strcpy(q->value, l, value);
8691  }
8692  if (q->domain)
8693  {
8694  if (!domain || strcmp(domain, q->domain))
8695  {
8696  SOAP_FREE(soap, q->domain);
8697  q->domain = NULL;
8698  }
8699  }
8700  if (domain && !q->domain)
8701  {
8702  size_t l = strlen(domain) + 1;
8703  q->domain = NULL;
8704  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
8705  q->domain = (char*)SOAP_MALLOC(soap, l);
8706  if (q->domain)
8707  soap_strcpy(q->domain, l, domain);
8708  }
8709  if (q->path)
8710  {
8711  if (!path || strncmp(path, q->path, strlen(q->path)))
8712  {
8713  SOAP_FREE(soap, q->path);
8714  q->path = NULL;
8715  }
8716  }
8717  if (path && !q->path)
8718  {
8719  size_t l = strlen(path) + 1;
8720  q->path = NULL;
8721  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
8722  q->path = (char*)SOAP_MALLOC(soap, l);
8723  if (q->path)
8724  soap_strcpy(q->path, l, path);
8725  }
8726  q->session = 1;
8727  q->env = 0;
8728  }
8729  return q;
8730 }
8731 
8732 /******************************************************************************/
8733 
8734 SOAP_FMAC1
8735 void
8736 SOAP_FMAC2
8737 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
8738 {
8739  struct soap_cookie **p, *q;
8740  if (!domain)
8742  if (!domain)
8743  {
8744  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)"));
8745  return;
8746  }
8747  if (!path)
8748  path = soap->cookie_path;
8749  if (!path)
8750  path = SOAP_STR_EOS;
8751  else if (*path == '/')
8752  path++;
8753  for (p = &soap->cookies, q = *p; q; q = *p)
8754  {
8755  if (!strcmp(q->name, name) && (!q->domain || !strcmp(q->domain, domain)) && (!q->path || !strncmp(q->path, path, strlen(q->path))))
8756  {
8757  SOAP_FREE(soap, q->name);
8758  if (q->value)
8759  SOAP_FREE(soap, q->value);
8760  if (q->domain)
8761  SOAP_FREE(soap, q->domain);
8762  if (q->path)
8763  SOAP_FREE(soap, q->path);
8764  *p = q->next;
8765  SOAP_FREE(soap, q);
8766  }
8767  else
8768  {
8769  p = &q->next;
8770  }
8771  }
8772 }
8773 
8774 /******************************************************************************/
8775 
8776 SOAP_FMAC1
8777 const char *
8778 SOAP_FMAC2
8779 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
8780 {
8781  struct soap_cookie *p;
8782  p = soap_cookie(soap, name, domain, path);
8783  if (p)
8784  return p->value;
8785  return NULL;
8786 }
8787 
8788 /******************************************************************************/
8789 
8790 SOAP_FMAC1
8791 const char *
8792 SOAP_FMAC2
8793 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
8794 {
8795  struct soap_cookie *p;
8796  p = soap_cookie(soap, name, domain, path);
8797  if (p && p->env)
8798  return p->value;
8799  return NULL;
8800 }
8801 
8802 /******************************************************************************/
8803 
8804 SOAP_FMAC1
8805 time_t
8806 SOAP_FMAC2
8807 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
8808 {
8809  struct soap_cookie *p;
8810  p = soap_cookie(soap, name, domain, path);
8811  if (p)
8812  return (time_t)p->expire;
8813  return -1;
8814 }
8815 
8816 /******************************************************************************/
8817 
8818 SOAP_FMAC1
8819 int
8820 SOAP_FMAC2
8821 soap_set_cookie_expire(struct soap *soap, const char *name, long maxage, const char *domain, const char *path)
8822 {
8823  struct soap_cookie *p;
8824  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", maxage, name, domain ? domain : "(null)", path ? path : "(null)"));
8825  p = soap_cookie(soap, name, domain, path);
8826  if (p)
8827  {
8828  p->maxage = maxage;
8829  p->modified = 1;
8830  return SOAP_OK;
8831  }
8832  return SOAP_ERR;
8833 }
8834 
8835 /******************************************************************************/
8836 
8837 SOAP_FMAC1
8838 int
8839 SOAP_FMAC2
8840 soap_set_cookie_secure(struct soap *soap, const char *name, const char *domain, const char *path)
8841 {
8842  struct soap_cookie *p;
8843  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie secure: cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)"));
8844  p = soap_cookie(soap, name, domain, path);
8845  if (p)
8846  {
8847  p->secure = 1;
8848  p->modified = 1;
8849  return SOAP_OK;
8850  }
8851  return SOAP_ERR;
8852 }
8853 /******************************************************************************/
8854 
8855 SOAP_FMAC1
8856 int
8857 SOAP_FMAC2
8858 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
8859 {
8860  struct soap_cookie *p;
8861  p = soap_cookie(soap, name, domain, path);
8862  if (p)
8863  {
8864  p->session = 1;
8865  p->modified = 1;
8866  return SOAP_OK;
8867  }
8868  return SOAP_ERR;
8869 }
8870 
8871 /******************************************************************************/
8872 
8873 SOAP_FMAC1
8874 int
8875 SOAP_FMAC2
8876 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
8877 {
8878  struct soap_cookie *p;
8879  p = soap_cookie(soap, name, domain, path);
8880  if (p)
8881  {
8882  p->session = 0;
8883  p->modified = 1;
8884  return SOAP_OK;
8885  }
8886  return SOAP_ERR;
8887 }
8888 
8889 /******************************************************************************/
8890 
8891 SOAP_FMAC1
8892 int
8893 SOAP_FMAC2
8894 soap_putsetcookies(struct soap *soap)
8895 {
8896  struct soap_cookie *p;
8897  char *s, tmp[4096];
8898  const char *t;
8899  for (p = soap->cookies; p; p = p->next)
8900  {
8901  if ((p->modified
8902 #ifdef WITH_OPENSSL
8903  || (!p->env && !soap->ssl == !p->secure)
8904 #endif
8905  ) && p->name && p->value && *p->name && *p->value)
8906  {
8907  s = tmp;
8908  s += soap_encode_url(p->name, s, 3967);
8909  *s++ = '=';
8910  s += soap_encode_url(p->value, s, 3968 - (int)(s-tmp));
8911  t = p->domain ? p->domain : soap->cookie_domain;
8912  if (t && (int)strlen(t) < 3968 - (int)(s-tmp))
8913  {
8914  soap_strcpy(s, 4096 - (s-tmp), ";Domain=");
8915  s += 8;
8916  soap_strcpy(s, 4096 - (s-tmp), t);
8917  s += strlen(s);
8918  }
8919  t = p->path ? p->path : soap->cookie_path;
8920  if (t && (int)strlen(t) < 3976 - (int)(s-tmp))
8921  {
8922  soap_strcpy(s, 4096 - (s-tmp), ";Path=/");
8923  s += 7;
8924  if (*t == '/')
8925  t++;
8926  if (strchr(t, '%')) /* already URL encoded? */
8927  {
8928  soap_strcpy(s, 4096 - (s-tmp), t);
8929  s += strlen(s);
8930  }
8931  else
8932  {
8933  s += soap_encode_url(t, s, 4096 - (int)(s-tmp));
8934  }
8935  }
8936  if (p->version > 0 && s-tmp < 3983)
8937  {
8938  (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Version=%u", p->version);
8939  s += strlen(s);
8940  }
8941  if (p->maxage >= 0 && s-tmp < 4012)
8942  {
8943  (SOAP_SNPRINTF(s, 4096 - (s-tmp), 29), ";Max-Age=%ld", p->maxage);
8944  s += strlen(s);
8945  }
8946 #if !defined(WITH_LEAN)
8947 #if defined(HAVE_GMTIME_R) || defined(HAVE_GMTIME)
8948  if (p->maxage >= 0 && s-tmp < 4041)
8949  {
8950  time_t n = time(NULL) + p->maxage;
8951  struct tm T, *pT = &T;
8952  size_t l = 0;
8953  /* format is Wed, 09 Jun 2021 10:18:14 GMT */
8954 #if defined(HAVE_GMTIME_R)
8955  if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR)
8956  l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT);
8957 #else
8958  pT = gmtime(&n);
8959  if (pT)
8960  l = strftime(s, 4096 - (s-tmp), ";Expires=%a, %d %b %Y %H:%M:%S GMT", pT);
8961 #endif
8962  s += l;
8963  }
8964 #endif
8965 #endif
8966  if (s-tmp < 4079
8967  && (p->secure
8968 #ifdef WITH_OPENSSL
8969  || soap->ssl
8970 #endif
8971  ))
8972  {
8973  soap_strcpy(s, 4096 - (s-tmp), ";Secure");
8974  s += strlen(s);
8975  }
8976  if (s-tmp < 4086)
8977  soap_strcpy(s, 4096 - (s-tmp), ";HttpOnly");
8978  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
8979  soap->error = soap->fposthdr(soap, "Set-Cookie", tmp);
8980  if (soap->error)
8981  return soap->error;
8982  }
8983  }
8984  return SOAP_OK;
8985 }
8986 
8987 /******************************************************************************/
8988 
8989 SOAP_FMAC1
8990 int
8991 SOAP_FMAC2
8992 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
8993 {
8994  struct soap_cookie **p, *q;
8995  char *s, tmp[4096];
8996  unsigned int version = 0;
8997  time_t now = time(NULL);
8998  if (!domain || !path)
8999  return SOAP_OK;
9000  s = tmp;
9001  p = &soap->cookies;
9002  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path));
9003  if (*path == '/')
9004  path++;
9005  while ((q = *p))
9006  {
9007  if (q->expire && now >= (time_t)q->expire)
9008  {
9009  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
9010  SOAP_FREE(soap, q->name);
9011  if (q->value)
9012  SOAP_FREE(soap, q->value);
9013  if (q->domain)
9014  SOAP_FREE(soap, q->domain);
9015  if (q->path)
9016  SOAP_FREE(soap, q->path);
9017  *p = q->next;
9018  SOAP_FREE(soap, q);
9019  }
9020  else
9021  {
9022  int flag;
9023  char *t = q->domain;
9024  size_t n = 0;
9025  if (!t)
9026  {
9027  flag = 1;
9028  }
9029  else
9030  {
9031  const char *r = strchr(t, ':');
9032  if (r)
9033  n = r - t;
9034  else
9035  n = strlen(t);
9036  flag = !strncmp(t, domain, n);
9037  }
9038  /* domain-level cookies, cannot compile when WITH_NOIO set */
9039 #ifndef WITH_NOIO
9040  if (!flag)
9041  {
9042  struct hostent hostent;
9043  if (!tcp_gethostbyname(soap, (char*)domain, &hostent, NULL))
9044  {
9045  const char *r = hostent.h_name;
9046  if (*t == '.')
9047  {
9048  size_t k = strlen(hostent.h_name);
9049  if (k >= n)
9050  r = hostent.h_name + k - n;
9051  }
9052  flag = !strncmp(t, r, n);
9053  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Domain cookie %s host %s (match=%d)\n", t, r, flag));
9054  }
9055  }
9056 #endif
9057  if (flag
9058  && (!q->path || !strncmp(q->path, path, strlen(q->path)))
9059 #ifndef WITH_INSECURE_COOKIES
9060  && (!q->secure || secure)
9061 #endif
9062  )
9063  {
9064  size_t n = 12;
9065  if (q->name)
9066  n += 3*strlen(q->name);
9067  if (q->value && *q->value)
9068  n += 3*strlen(q->value) + 1;
9069  if (q->path && *q->path)
9070  n += strlen(q->path) + 9;
9071  if (q->domain)
9072  n += strlen(q->domain) + 11;
9073  if (s + n >= tmp + sizeof(tmp))
9074  {
9075  if (s == tmp)
9076  return SOAP_OK; /* header too big, cannot split */
9077  /* split up HTTP header */
9078  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
9079  soap->error = soap->fposthdr(soap, "Cookie", tmp);
9080  if (soap->error)
9081  return soap->error;
9082  s = tmp;
9083  }
9084  else if (s != tmp)
9085  {
9086  *s++ = ';';
9087  }
9088  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookie %s=%s path=\"/%s\" domain=\"%s\"\n", q->name ? q->name : "(null)", q->value ? q->value : "(null)", q->path ? q->path : "(null)", q->domain ? q->domain : "(null)"));
9089  if (q->version != version && (s-tmp) + (size_t)36 < sizeof(tmp))
9090  {
9091  (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), "$Version=%u;", q->version);
9092  version = q->version;
9093  s += strlen(s);
9094  }
9095  if (q->name && (s-tmp) + strlen(q->name) + (size_t)15 < sizeof(tmp))
9096  {
9097  s += soap_encode_url(q->name, s, (int)(tmp+sizeof(tmp)-s)-15);
9098  }
9099  if (q->value && *q->value && (s-tmp) + strlen(q->value) + (size_t)16 < sizeof(tmp))
9100  {
9101  *s++ = '=';
9102  s += soap_encode_url(q->value, s, (int)(tmp+sizeof(tmp)-s)-16);
9103  }
9104  if (q->path && (s-tmp) + strlen(q->path) + (size_t)36 < sizeof(tmp))
9105  {
9106  (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
9107  s += strlen(s);
9108  }
9109  if (q->domain && (s-tmp) + strlen(q->domain) + (size_t)36 < sizeof(tmp))
9110  {
9111  (SOAP_SNPRINTF_SAFE(s, sizeof(tmp) - (s-tmp)), ";$Domain=\"%s\"", q->domain);
9112  s += strlen(s);
9113  }
9114  }
9115  p = &q->next;
9116  }
9117  }
9118  if (s != tmp)
9119  {
9120  soap->error = soap->fposthdr(soap, "Cookie", tmp);
9121  if (soap->error)
9122  return soap->error;
9123  }
9124  return SOAP_OK;
9125 }
9126 
9127 /******************************************************************************/
9128 
9129 SOAP_FMAC1
9130 void
9131 SOAP_FMAC2
9132 soap_getcookies(struct soap *soap, const char *val)
9133 {
9134  struct soap_cookie *p = NULL, *q = NULL;
9135  const char *s;
9136  char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
9137  char *domain = NULL;
9138  char *path = NULL;
9139  unsigned int version = 0;
9140  time_t now = time(NULL);
9141  if (!val)
9142  return;
9143  s = val;
9144  while (*s)
9145  {
9146  s = soap_decode_key(tmp, sizeof(tmp), s);
9147  if (!soap_tag_cmp(tmp, "$Version"))
9148  {
9149  s = soap_decode_val(tmp, sizeof(tmp), s);
9150  if (s)
9151  {
9152  if (p)
9153  p->version = (int)soap_strtol(tmp, NULL, 10);
9154  else
9155  version = (int)soap_strtol(tmp, NULL, 10);
9156  }
9157  }
9158  else if (!soap_tag_cmp(tmp, "$Path"))
9159  {
9160  s = soap_decode_val(tmp, sizeof(tmp), s);
9161  t = NULL;
9162  if (*tmp)
9163  {
9164  size_t l = strlen(tmp) + 1;
9165  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9166  t = (char*)SOAP_MALLOC(soap, l);
9167  if (t)
9168  (void)soap_memcpy((void*)t, l, (const void*)tmp, l);
9169  }
9170  if (p)
9171  {
9172  if (p->path)
9173  SOAP_FREE(soap, p->path);
9174  p->path = t;
9175  }
9176  else
9177  {
9178  if (path)
9179  SOAP_FREE(soap, path);
9180  path = t;
9181  }
9182  }
9183  else if (!soap_tag_cmp(tmp, "$Domain"))
9184  {
9185  s = soap_decode_val(tmp, sizeof(tmp), s);
9186  t = NULL;
9187  if (*tmp)
9188  {
9189  size_t l = strlen(tmp) + 1;
9190  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9191  t = (char*)SOAP_MALLOC(soap, l);
9192  if (t)
9193  (void)soap_memcpy((void*)t, l, (const void*)tmp, l);
9194  }
9195  if (p)
9196  {
9197  if (p->domain)
9198  SOAP_FREE(soap, p->domain);
9199  p->domain = t;
9200  }
9201  else
9202  {
9203  if (domain)
9204  SOAP_FREE(soap, domain);
9205  domain = t;
9206  }
9207  }
9208  else if (p && !soap_tag_cmp(tmp, "Path"))
9209  {
9210  if (p->path)
9211  SOAP_FREE(soap, p->path);
9212  p->path = NULL;
9213  s = soap_decode_val(tmp, sizeof(tmp), s);
9214  if (*tmp)
9215  {
9216  size_t l = strlen(tmp) + 1;
9217  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9218  p->path = (char*)SOAP_MALLOC(soap, l);
9219  if (p->path)
9220  (void)soap_memcpy((void*)p->path, l, (const void*)tmp, l);
9221  }
9222  }
9223  else if (p && !soap_tag_cmp(tmp, "Domain"))
9224  {
9225  if (p->domain)
9226  SOAP_FREE(soap, p->domain);
9227  p->domain = NULL;
9228  s = soap_decode_val(tmp, sizeof(tmp), s);
9229  if (*tmp)
9230  {
9231  size_t l = strlen(tmp) + 1;
9232  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9233  p->domain = (char*)SOAP_MALLOC(soap, l);
9234  if (p->domain)
9235  (void)soap_memcpy((void*)p->domain, l, (const void*)tmp, l);
9236  }
9237  }
9238  else if (p && !soap_tag_cmp(tmp, "Version"))
9239  {
9240  s = soap_decode_val(tmp, sizeof(tmp), s);
9241  p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
9242  }
9243  else if (p && !soap_tag_cmp(tmp, "Max-Age"))
9244  {
9245  s = soap_decode_val(tmp, sizeof(tmp), s);
9246  p->expire = (ULONG64)(now + soap_strtol(tmp, NULL, 10));
9247  }
9248  else if (p && !soap_tag_cmp(tmp, "Expires"))
9249  {
9250  if (*s == '=')
9251  {
9252  s = soap_decode(tmp, sizeof(tmp), s + 1, ";");
9253  if (!p->expire && strlen(tmp) >= 23)
9254  {
9255  char a[3];
9256  struct tm T;
9257  static const char mns[] = "anebarprayunulugepctovec";
9258  const char *t = strchr(tmp, ' ');
9259  if (t)
9260  {
9261  a[2] = '\0';
9262  memset((void*)&T, 0, sizeof(T));
9263  if (t[1] >= 'A')
9264  {
9265  /* format is Sun Nov 6 08:49:37 94 */
9266  a[0] = t[2];
9267  a[1] = t[3];
9268  T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
9269  a[0] = t[5];
9270  a[1] = t[6];
9271  T.tm_mday = (int)soap_strtol(a, NULL, 10);
9272  if (t[17] && t[18] && t[19] != ' ')
9273  t += 2; /* format is Sun Nov 6 08:49:37 2017 - ANSI-C */
9274  a[0] = t[17];
9275  a[1] = t[18];
9276  T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
9277  t += 6;
9278  }
9279  else
9280  {
9281  /* format is Sunday, 06-Nov-17 08:49:37 GMT - RFC 850 */
9282  a[0] = t[1];
9283  a[1] = t[2];
9284  T.tm_mday = (int)soap_strtol(a, NULL, 10);
9285  a[0] = t[5];
9286  a[1] = t[6];
9287  T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
9288  if (t[10] != ' ')
9289  t += 2; /* format is Wed, 09 Jun 2021 10:18:14 GMT - RFC 822 */
9290  a[0] = t[8];
9291  a[1] = t[9];
9292  T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
9293  t += 11;
9294  }
9295  a[0] = t[0];
9296  a[1] = t[1];
9297  T.tm_hour = (int)soap_strtol(a, NULL, 10);
9298  a[0] = t[3];
9299  a[1] = t[4];
9300  T.tm_min = (int)soap_strtol(a, NULL, 10);
9301  a[0] = t[6];
9302  a[1] = t[7];
9303  T.tm_sec = (int)soap_strtol(a, NULL, 10);
9304  p->expire = (ULONG64)soap_timegm(&T);
9305  }
9306  }
9307  }
9308  }
9309  else if (p && !soap_tag_cmp(tmp, "Secure"))
9310  {
9311  p->secure = 1;
9312  s = soap_decode_val(tmp, sizeof(tmp), s);
9313  }
9314  else if (p && !soap_tag_cmp(tmp, "HttpOnly"))
9315  {
9316  s = soap_decode_val(tmp, sizeof(tmp), s);
9317  }
9318  else if (p && !soap_tag_cmp(tmp, "Comment"))
9319  {
9320  s = soap_decode_val(tmp, sizeof(tmp), s);
9321  }
9322  else if (*tmp)
9323  {
9324  if (p)
9325  {
9326  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=" SOAP_ULONG_FORMAT " secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
9327  q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path);
9328  if (q)
9329  {
9330  q->version = p->version;
9331  q->expire = p->expire;
9332  q->secure = p->secure;
9333  q->env = 1;
9334  }
9335  if (p->name)
9336  SOAP_FREE(soap, p->name);
9337  if (p->value)
9338  SOAP_FREE(soap, p->value);
9339  if (p->domain)
9340  SOAP_FREE(soap, p->domain);
9341  if (p->path)
9342  SOAP_FREE(soap, p->path);
9343  SOAP_FREE(soap, p);
9344  }
9345  p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie));
9346  if (p)
9347  {
9348  size_t l = strlen(tmp) + 1;
9349  p->name = NULL;
9350  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9351  p->name = (char*)SOAP_MALLOC(soap, l);
9352  if (p->name)
9353  (void)soap_memcpy(p->name, l, tmp, l);
9354  s = soap_decode_val(tmp, sizeof(tmp), s);
9355  p->value = NULL;
9356  if (*tmp)
9357  {
9358  l = strlen(tmp) + 1;
9359  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9360  p->value = (char*)SOAP_MALLOC(soap, l);
9361  if (p->value)
9362  (void)soap_memcpy((void*)p->value, l, (const void*)tmp, l);
9363  }
9364  if (domain)
9365  {
9366  p->domain = domain;
9367  domain = NULL;
9368  }
9369  else
9370  {
9371  p->domain = NULL;
9372  }
9373  if (path)
9374  {
9375  p->path = path;
9376  path = NULL;
9377  }
9378  else if (*soap->path)
9379  {
9380  l = strlen(soap->path) + 1;
9381  p->path = NULL;
9382  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9383  p->path = (char*)SOAP_MALLOC(soap, l);
9384  if (p->path)
9385  (void)soap_memcpy((void*)p->path, l, (const void*)soap->path, l);
9386  }
9387  else
9388  {
9389  p->path = (char*)SOAP_MALLOC(soap, 2);
9390  if (p->path)
9391  (void)soap_memcpy((void*)p->path, 2, (const void*)"/", 2);
9392  }
9393  p->expire = 0;
9394  p->secure = 0;
9395  p->version = version;
9396  }
9397  }
9398  }
9399  if (p)
9400  {
9401  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=" SOAP_ULONG_FORMAT " secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
9402  q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path);
9403  if (q)
9404  {
9405  q->version = p->version;
9406  q->expire = p->expire;
9407  q->secure = p->secure;
9408  q->env = 1;
9409  }
9410  if (p->name)
9411  SOAP_FREE(soap, p->name);
9412  if (p->value)
9413  SOAP_FREE(soap, p->value);
9414  if (p->domain)
9415  SOAP_FREE(soap, p->domain);
9416  if (p->path)
9417  SOAP_FREE(soap, p->path);
9418  SOAP_FREE(soap, p);
9419  }
9420  if (domain)
9421  SOAP_FREE(soap, domain);
9422  if (path)
9423  SOAP_FREE(soap, path);
9424 }
9425 
9426 /******************************************************************************/
9427 
9428 SOAP_FMAC1
9429 int
9430 SOAP_FMAC2
9431 soap_getenv_cookies(struct soap *soap)
9432 {
9433  struct soap_cookie *p;
9434  const char *s;
9435  char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
9436  s = getenv("HTTP_COOKIE");
9437  if (!s)
9438  return SOAP_ERR;
9439  do
9440  {
9441  s = soap_decode_key(key, sizeof(key), s);
9442  s = soap_decode_val(val, sizeof(val), s);
9443  p = soap_set_cookie(soap, key, val, NULL, NULL);
9444  if (p)
9445  p->env = 1;
9446  } while (*s);
9447  return SOAP_OK;
9448 }
9449 
9450 /******************************************************************************/
9451 
9452 SOAP_FMAC1
9453 struct soap_cookie*
9454 SOAP_FMAC2
9455 soap_copy_cookies(struct soap *copy, const struct soap *soap)
9456 {
9457  struct soap_cookie *p, **q, *r;
9458  (void)copy;
9459  q = &r;
9460  for (p = soap->cookies; p; p = p->next)
9461  {
9462  *q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie));
9463  if (!*q)
9464  return r;
9465  **q = *p;
9466  if (p->name)
9467  {
9468  size_t l = strlen(p->name) + 1;
9469  (*q)->name = NULL;
9470  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9471  (*q)->name = (char*)SOAP_MALLOC(copy, l);
9472  if ((*q)->name)
9473  (void)soap_memcpy((*q)->name, l, p->name, l);
9474  }
9475  if (p->value)
9476  {
9477  size_t l = strlen(p->value) + 1;
9478  (*q)->value = NULL;
9479  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9480  (*q)->value = (char*)SOAP_MALLOC(copy, l);
9481  if ((*q)->value)
9482  (void)soap_memcpy((*q)->value, l, p->value, l);
9483  }
9484  if (p->domain)
9485  {
9486  size_t l = strlen(p->domain) + 1;
9487  (*q)->domain = NULL;
9488  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9489  (*q)->domain = (char*)SOAP_MALLOC(copy, l);
9490  if ((*q)->domain)
9491  (void)soap_memcpy((*q)->domain, l, p->domain, l);
9492  }
9493  if (p->path)
9494  {
9495  size_t l = strlen(p->path) + 1;
9496  (*q)->path = NULL;
9497  if (SOAP_MAXALLOCSIZE <= 0 || l <= SOAP_MAXALLOCSIZE)
9498  (*q)->path = (char*)SOAP_MALLOC(copy, l);
9499  if ((*q)->path)
9500  (void)soap_memcpy((*q)->path, l, p->path, l);
9501  }
9502  q = &(*q)->next;
9503  }
9504  *q = NULL;
9505  return r;
9506 }
9507 
9508 /******************************************************************************/
9509 
9510 SOAP_FMAC1
9511 void
9512 SOAP_FMAC2
9513 soap_free_cookies(struct soap *soap)
9514 {
9515  struct soap_cookie *p;
9516  for (p = soap->cookies; p; p = soap->cookies)
9517  {
9518  soap->cookies = p->next;
9519  SOAP_FREE(soap, p->name);
9520  if (p->value)
9521  SOAP_FREE(soap, p->value);
9522  if (p->domain)
9523  SOAP_FREE(soap, p->domain);
9524  if (p->path)
9525  SOAP_FREE(soap, p->path);
9526  SOAP_FREE(soap, p);
9527  }
9528 }
9529 
9530 /******************************************************************************/
9531 
9532 #endif /* WITH_COOKIES */
9533 
9534 /******************************************************************************/
9535 
9536 SOAP_FMAC1
9537 size_t
9538 SOAP_FMAC2
9539 soap_hash(const char *s)
9540 {
9541  size_t h = 0;
9542  while (*s)
9543  h = *s++ + (h << 6) + (h << 16) - h; /* Red Dragon book h = 65599*h + c */
9544  return h % SOAP_IDHASH;
9545 }
9546 
9547 /******************************************************************************/
9548 
9549 static void
9551 {
9552  int i;
9553  soap->pblk = NULL;
9554  soap->pidx = 0;
9555  for (i = 0; i < (int)SOAP_PTRHASH; i++)
9556  soap->pht[i] = NULL;
9557 }
9558 
9559 /******************************************************************************/
9560 
9561 SOAP_FMAC1
9562 struct soap*
9563 SOAP_FMAC2
9565 {
9566  struct soap *soap;
9567 #ifdef __cplusplus
9568  soap = SOAP_NEW_UNMANAGED(struct soap);
9569 #else
9570  soap = (struct soap*)SOAP_MALLOC_UNMANAGED(sizeof(struct soap));
9571 #endif
9572  if (soap)
9574  return soap;
9575 }
9576 
9577 /******************************************************************************/
9578 
9579 SOAP_FMAC1
9580 void
9581 SOAP_FMAC2
9583 {
9584  soap_done(soap);
9585 #ifdef __cplusplus
9587 #else
9589 #endif
9590 }
9591 
9592 /******************************************************************************/
9593 
9594 SOAP_FMAC1
9595 void
9596 SOAP_FMAC2
9598 {
9599  free(soap);
9600 }
9601 
9602 /******************************************************************************/
9603 
9604 static void
9606 {
9607  struct soap_pblk *pb, *next;
9608  int i;
9609  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
9610  for (pb = soap->pblk; pb; pb = next)
9611  {
9612  next = pb->next;
9613  SOAP_FREE(soap, pb);
9614  }
9615  soap->pblk = NULL;
9616  soap->pidx = 0;
9617  for (i = 0; i < (int)SOAP_PTRHASH; i++)
9618  soap->pht[i] = NULL;
9619 }
9620 
9621 /******************************************************************************/
9622 
9623 #ifndef WITH_NOIDREF
9624 SOAP_FMAC1
9625 int
9626 SOAP_FMAC2
9627 soap_embed(struct soap *soap, const void *p, const void *a, int n, int t)
9628 {
9629  int id;
9630  struct soap_plist *pp;
9631  if (soap->version == 2)
9632  soap->encoding = 1;
9633  if (!p || (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE))
9634  return 0;
9635  if (a)
9636  id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
9637  else
9638  id = soap_pointer_lookup(soap, p, t, &pp);
9639  if (id)
9640  {
9641  if (soap_is_embedded(soap, pp) || soap_is_single(soap, pp))
9642  return 0;
9643  soap_set_embedded(soap, pp);
9644  }
9645  return id;
9646 }
9647 #endif
9648 
9649 /******************************************************************************/
9650 
9651 SOAP_FMAC1
9652 int
9653 SOAP_FMAC2
9654 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
9655 {
9656  struct soap_plist *pp;
9657  *ppp = NULL;
9658  if (p)
9659  {
9660  for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
9661  {
9662  if (pp->ptr == p && pp->type == type)
9663  {
9664  *ppp = pp;
9665  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
9666  return pp->id;
9667  }
9668  }
9669  }
9670  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
9671  return 0;
9672 }
9673 
9674 /******************************************************************************/
9675 
9676 SOAP_FMAC1
9677 int
9678 SOAP_FMAC2
9679 soap_pointer_enter(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp)
9680 {
9681  size_t h;
9682  struct soap_plist *pp;
9683  (void)n;
9684  if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
9685  {
9686  struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
9687  if (!pb)
9688  {
9689  soap->error = SOAP_EOM;
9690  return 0;
9691  }
9692  pb->next = soap->pblk;
9693  soap->pblk = pb;
9694  soap->pidx = 0;
9695  }
9696  *ppp = pp = &soap->pblk->plist[soap->pidx++];
9697  if (a)
9698  h = soap_hash_ptr(a);
9699  else
9700  h = soap_hash_ptr(p);
9701  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%lu type=%d id=%d\n", p, a, (unsigned long)n, type, soap->idnum+1));
9702  pp->next = soap->pht[h];
9703  pp->type = type;
9704  pp->mark1 = 0;
9705  pp->mark2 = 0;
9706  pp->ptr = p;
9707  pp->dup = NULL;
9708  pp->array = a;
9709  pp->size = n;
9710  soap->pht[h] = pp;
9711  pp->id = ++soap->idnum;
9712  return pp->id;
9713 }
9714 
9715 /******************************************************************************/
9716 
9717 SOAP_FMAC1
9718 int
9719 SOAP_FMAC2
9720 soap_array_pointer_lookup(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp)
9721 {
9722  struct soap_plist *pp;
9723  *ppp = NULL;
9724  if (!p || !a)
9725  return 0;
9726  for (pp = soap->pht[soap_hash_ptr(a)]; pp; pp = pp->next)
9727  {
9728  if (pp->type == type && pp->array == a && pp->size == n)
9729  {
9730  *ppp = pp;
9731  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a, type, pp->id));
9732  return pp->id;
9733  }
9734  }
9735  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a, type));
9736  return 0;
9737 }
9738 
9739 /******************************************************************************/
9740 
9741 SOAP_FMAC1
9742 int
9743 SOAP_FMAC2
9745 {
9746  soap_free_ns(soap);
9747  soap->error = SOAP_OK;
9748 #ifndef WITH_LEANER
9749  if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
9750  {
9752  }
9753  else
9754 #endif
9755  {
9756  soap->mode = soap->omode;
9757  if ((soap->mode & SOAP_IO_UDP))
9758  {
9759  soap->mode &= SOAP_IO;
9761  }
9762  if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
9763  || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_PLAIN))
9764 #ifndef WITH_LEANER
9765  && !soap->fpreparesend
9766 #endif
9767  ))
9768  soap->mode &= ~SOAP_IO_LENGTH;
9769  else
9770  soap->mode |= SOAP_IO_LENGTH;
9771  }
9772 #ifdef WITH_ZLIB
9773  if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
9774  {
9775  if (!(soap->mode & SOAP_ENC_DIME))
9776  soap->mode &= ~SOAP_IO_LENGTH;
9777  if ((soap->mode & SOAP_ENC_PLAIN))
9778  soap->mode |= SOAP_IO_BUFFER;
9779  else
9780  soap->mode |= SOAP_IO_STORE;
9781  }
9782 #endif
9783 #ifndef WITH_LEANER
9784  if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
9785  soap->mode |= SOAP_ENC_MIME;
9786  else if (!(soap->mode & SOAP_ENC_MIME))
9787  soap->mode &= ~SOAP_ENC_MTOM;
9788  if ((soap->mode & SOAP_ENC_MIME))
9790  soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
9791 #endif
9792  soap->count = 0;
9793  soap->ns = 0;
9794  soap->null = 0;
9795  soap->position = 0;
9796  soap->mustUnderstand = 0;
9797  soap->encoding = 0;
9799  soap->event = 0;
9800  soap->evlev = 0;
9801  soap->idnum = 0;
9802  soap->body = 1;
9803  soap->level = 0;
9806 #ifndef WITH_LEANER
9807  soap->dime.size = 0; /* accumulate total size of attachments */
9809  return soap->error;
9810 #endif
9811  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=" SOAP_ULONG_FORMAT ")\n", (int)soap->socket, (unsigned int)soap->mode, soap->count));
9812 #ifndef WITH_LEANER
9813  if ((soap->mode & SOAP_IO_LENGTH))
9814  return soap_begin_attachments(soap);
9815 #endif
9816  return SOAP_OK;
9817 }
9818 
9819 /******************************************************************************/
9820 
9821 SOAP_FMAC1
9822 int
9823 SOAP_FMAC2
9825 {
9826  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
9827 #ifndef WITH_LEANER
9828  if ((soap->mode & SOAP_IO_LENGTH))
9829  {
9831  return soap->error;
9833  return soap->error;
9834  }
9835 #else
9836  (void)soap;
9837 #endif
9838  return SOAP_OK;
9839 }
9840 
9841 /******************************************************************************/
9842 
9843 static int
9845 {
9846  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", (int)soap->socket, soap->sendfd));
9847  *soap->tag = '\0';
9848  soap_free_ns(soap);
9849  soap->error = SOAP_OK;
9851 #ifndef WITH_LEAN
9852  if ((soap->mode & SOAP_IO_UDP))
9853  {
9854  soap->mode &= ~SOAP_IO;
9856  if ((soap->mode & SOAP_IO_LENGTH) && soap->count > sizeof(soap->buf))
9857  return soap->error = SOAP_UDP_ERROR;
9858  }
9859 #endif
9860 #ifdef WITH_ZLIB
9861  if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
9862  {
9863  if ((soap->mode & SOAP_ENC_PLAIN))
9864  soap->mode |= SOAP_IO_BUFFER;
9865  else
9866  soap->mode |= SOAP_IO_STORE;
9867  }
9868 #endif
9869 #if !defined(__cplusplus) || defined(WITH_COMPAT)
9870  if (soap->os)
9871  {
9872  *soap->os = NULL;
9873  soap->mode = (soap->mode & ~SOAP_IO) | SOAP_IO_STORE;
9874  }
9875  else
9876 #endif
9878  {
9879  if ((soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_PLAIN))
9880  soap->mode |= SOAP_IO_BUFFER;
9881  else
9882  soap->mode |= SOAP_IO_STORE;
9883  }
9884  soap->mode &= ~SOAP_IO_LENGTH;
9886  return soap->error;
9887  if (!(soap->mode & SOAP_IO_KEEPALIVE))
9888  soap->keep_alive = 0;
9889 #ifndef WITH_LEANER
9891  {
9892  soap->mode |= SOAP_ENC_MIME;
9893  soap->mode &= ~SOAP_ENC_DIME;
9894  }
9895  else if (!(soap->mode & SOAP_ENC_MIME))
9896  {
9897  soap->mode &= ~SOAP_ENC_MTOM;
9898  }
9899  if ((soap->mode & SOAP_ENC_MIME))
9901 #ifdef WIN32
9902 #ifndef UNDER_CE
9903 #ifndef WITH_FASTCGI
9904  if (!soap_valid_socket(soap->socket) && !soap->os && soap->sendfd >= 0) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
9905 #ifdef __BORLANDC__
9906  setmode(soap->sendfd, _O_BINARY);
9907 #else
9908  _setmode(soap->sendfd, _O_BINARY);
9909 #endif
9910 #endif
9911 #endif
9912 #endif
9913 #endif
9914  if ((soap->mode & SOAP_IO))
9915  soap->buflen = soap->bufidx = 0;
9916  soap->chunksize = 0;
9917  soap->ns = 0;
9918  soap->null = 0;
9919  soap->position = 0;
9920  soap->mustUnderstand = 0;
9921  soap->encoding = 0;
9922  soap->event = 0;
9923  soap->evlev = 0;
9924  soap->idnum = 0;
9925  soap->body = 1;
9926  soap->level = 0;
9929 #ifdef WITH_ZLIB
9930  soap->z_ratio_out = 1.0;
9932  {
9933  if (!soap->d_stream)
9934  {
9935  soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
9936  if (!soap->d_stream)
9937  return soap->error = SOAP_EOM;
9938  soap->d_stream->zalloc = Z_NULL;
9939  soap->d_stream->zfree = Z_NULL;
9940  soap->d_stream->opaque = Z_NULL;
9941  soap->d_stream->next_in = Z_NULL;
9942  }
9943  if (!soap->z_buf)
9944  soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
9945  if (!soap->z_buf)
9946  return soap->error = SOAP_EOM;
9947  soap->d_stream->next_out = (Byte*)soap->z_buf;
9948  soap->d_stream->avail_out = sizeof(soap->buf);
9949 #ifdef WITH_GZIP
9951  {
9952  (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)"\37\213\10\0\0\0\0\0\0\377", 10);
9953  soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
9954  soap->d_stream->avail_out = sizeof(soap->buf) - 10;
9955  soap->z_crc = crc32(0L, NULL, 0);
9957  if (soap->z_dict)
9958  *((Byte*)soap->z_buf + 2) = 0xff;
9960  return soap->error = SOAP_ZLIB_ERROR;
9961  }
9962  else
9963 #endif
9965  return soap->error = SOAP_ZLIB_ERROR;
9966  if (soap->z_dict)
9967  {
9969  return soap->error = SOAP_ZLIB_ERROR;
9970  }
9971  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
9973  }
9974 #endif
9975 #ifdef WITH_OPENSSL
9976  if (soap->ssl)
9977  ERR_clear_error();
9978 #endif
9979  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=" SOAP_ULONG_FORMAT ")\n", (int)soap->socket, soap->mode, soap->count));
9981 #ifndef WITH_LEANER
9983  return soap->error;
9984 #endif
9985 #ifndef WITH_LEAN
9986  soap->start = (ULONG64)time(NULL);
9987 #endif
9988  return SOAP_OK;
9989 }
9990 
9991 /******************************************************************************/
9992 
9993 SOAP_FMAC1
9994 int
9995 SOAP_FMAC2
9997 {
9998 #ifndef WITH_LEANER
9999  if (soap_init_send(soap))
10000  return soap->error;
10001  return soap_begin_attachments(soap);
10002 #else
10003  return soap_init_send(soap);
10004 #endif
10005 }
10006 
10007 /******************************************************************************/
10008 
10009 #ifndef WITH_NOIDREF
10010 SOAP_FMAC1
10011 void
10012 SOAP_FMAC2
10013 soap_embedded(struct soap *soap, const void *p, int t)
10014 {
10015  struct soap_plist *pp;
10016  if (soap_pointer_lookup(soap, p, t, &pp))
10017  {
10018  pp->mark1 = 1;
10019  pp->mark2 = 1;
10020  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
10021  }
10022 }
10023 #endif
10024 
10025 /******************************************************************************/
10026 
10027 #ifndef WITH_NOIDREF
10028 SOAP_FMAC1
10029 int
10030 SOAP_FMAC2
10031 soap_reference(struct soap *soap, const void *p, int t)
10032 {
10033  struct soap_plist *pp;
10035  return 1;
10036  if (soap_pointer_lookup(soap, p, t, &pp))
10037  {
10038  if (pp->mark1 == 0)
10039  {
10040  pp->mark1 = 2;
10041  pp->mark2 = 2;
10042  }
10043  }
10044  else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
10045  {
10046  return 1;
10047  }
10048  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
10049  return pp->mark1;
10050 }
10051 #endif
10052 
10053 /******************************************************************************/
10054 
10055 #ifndef WITH_NOIDREF
10056 SOAP_FMAC1
10057 int
10058 SOAP_FMAC2
10059 soap_array_reference(struct soap *soap, const void *p, const void *a, int n, int t)
10060 {
10061  struct soap_plist *pp;
10062  if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
10063  return 1;
10064  if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
10065  {
10066  if (pp->mark1 == 0)
10067  {
10068  pp->mark1 = 2;
10069  pp->mark2 = 2;
10070  }
10071  }
10072  else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
10073  {
10074  return 1;
10075  }
10076  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long)n, t, (int)pp->mark1, (int)pp->mark2));
10077  return pp->mark1;
10078 }
10079 #endif
10080 
10081 /******************************************************************************/
10082 
10083 #ifndef WITH_NOIDREF
10084 SOAP_FMAC1
10085 int
10086 SOAP_FMAC2
10087 soap_attachment_reference(struct soap *soap, const void *p, const void *a, int n, int t, const char *id, const char *type)
10088 {
10089  struct soap_plist *pp;
10090  if (!p || !a || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH) && !id && !type) || (soap->omode & SOAP_XML_TREE))
10091  return 1;
10092  if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
10093  {
10094  if (pp->mark1 == 0)
10095  {
10096  pp->mark1 = 2;
10097  pp->mark2 = 2;
10098  }
10099  }
10100  else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
10101  {
10102  return 1;
10103  }
10104  if (id || type)
10105  soap->mode |= SOAP_ENC_DIME;
10106  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment reference %p ptr=%p n=%lu t=%d (%d %d)\n", p, a, (unsigned long)n, t, (int)pp->mark1, (int)pp->mark2));
10107  return pp->mark1;
10108 }
10109 #endif
10110 
10111 /******************************************************************************/
10112 
10113 #ifndef WITH_NOIDREF
10114 SOAP_FMAC1
10115 int
10116 SOAP_FMAC2
10117 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
10118 {
10119  struct soap_plist *pp = NULL;
10120  if (id >= 0 || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
10121  return id;
10122  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
10123  if (id < -1)
10124  return soap_embed(soap, p, NULL, 0, t);
10125  if (id < 0)
10126  {
10127  id = soap_pointer_lookup(soap, p, t, &pp);
10128  if (soap->version == 1 && soap->part != SOAP_IN_HEADER)
10129  {
10130  if (id)
10131  {
10132  if ((soap->mode & SOAP_IO_LENGTH))
10133  pp->mark1 = 2;
10134  else
10135  pp->mark2 = 2;
10136  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
10137  }
10138  return -1;
10139  }
10140  else if (id)
10141  {
10142  if ((soap->mode & SOAP_IO_LENGTH))
10143  pp->mark1 = 1;
10144  else
10145  pp->mark2 = 1;
10146  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
10147  }
10148  }
10149  return id;
10150 }
10151 #endif
10152 
10153 /******************************************************************************/
10154 
10155 #ifndef WITH_NOIDREF
10156 SOAP_FMAC1
10157 int
10158 SOAP_FMAC2
10159 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
10160 {
10161  if (!pp)
10162  return 0;
10163  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
10165  {
10166  if ((soap->mode & SOAP_IO_LENGTH))
10167  return pp->mark1 != 0;
10168  return pp->mark2 != 0;
10169  }
10170  if ((soap->mode & SOAP_IO_LENGTH))
10171  return pp->mark1 == 1;
10172  return pp->mark2 == 1;
10173 }
10174 #endif
10175 
10176 /******************************************************************************/
10177 
10178 #ifndef WITH_NOIDREF
10179 SOAP_FMAC1
10180 int
10181 SOAP_FMAC2
10182 soap_is_single(struct soap *soap, struct soap_plist *pp)
10183 {
10184  if (soap->part == SOAP_IN_HEADER)
10185  return 1;
10186  if (!pp)
10187  return 0;
10188  if ((soap->mode & SOAP_IO_LENGTH))
10189  return pp->mark1 == 0;
10190  return pp->mark2 == 0;
10191 }
10192 #endif
10193 
10194 /******************************************************************************/
10195 
10196 #ifndef WITH_NOIDREF
10197 SOAP_FMAC1
10198 void
10199 SOAP_FMAC2
10201 {
10202  if (!pp)
10203  return;
10204  if ((soap->mode & SOAP_IO_LENGTH))
10205  pp->mark1 = 1;
10206  else
10207  pp->mark2 = 1;
10208 }
10209 #endif
10210 
10211 /******************************************************************************/
10212 
10213 #ifndef WITH_LEANER
10214 SOAP_FMAC1
10215 int
10216 SOAP_FMAC2
10217 soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *aid, const char *atype, const char *aoptions, const char *type, int t)
10218 {
10219  struct soap_plist *pp;
10220  int i;
10221  if (!p || !a || (!aid && !atype) || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME | SOAP_ENC_MIME | SOAP_ENC_MTOM | SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
10222  return soap_element_id(soap, tag, id, p, a, n, type, t, NULL);
10223  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid ? aid : SOAP_STR_EOS, id, atype ? atype : SOAP_STR_EOS));
10224  i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
10225  if (!i)
10226  {
10227  i = soap_pointer_enter(soap, p, a, n, t, &pp);
10228  if (!i)
10229  {
10230  soap->error = SOAP_EOM;
10231  return -1;
10232  }
10233  }
10234  if (id <= 0)
10235  id = i;
10236  if (!aid)
10237  {
10238  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->dime_id_format) + 20), soap->dime_id_format, id);
10239  aid = soap_strdup(soap, soap->tmpbuf);
10240  if (!aid)
10241  return -1;
10242  }
10243  /* Add MTOM xop:Include element when necessary */
10244  /* TODO: this code to be obsoleted with new import/xop.h conventions */
10245  if ((soap->omode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
10246  {
10247  if (soap_element_begin_out(soap, tag, 0, type)
10248  || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
10249  || soap_element_end_out(soap, tag))
10250  return soap->error;
10251  }
10252  else if (soap_element_href(soap, tag, 0, "href", aid))
10253  {
10254  return soap->error;
10255  }
10256  if ((soap->mode & SOAP_IO_LENGTH))
10257  {
10258  if (pp->mark1 != 3)
10259  {
10260  struct soap_multipart *content;
10261  if ((soap->omode & SOAP_ENC_MTOM))
10262  content = soap_alloc_multipart(soap, &soap->mime.first, &soap->mime.last, (const char*)a, n);
10263  else
10264  content = soap_alloc_multipart(soap, &soap->dime.first, &soap->dime.last, (const char*)a, n);
10265  if (!content)
10266  {
10267  soap->error = SOAP_EOM;
10268  return -1;
10269  }
10270  if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
10271  {
10272  if ((soap->omode & SOAP_ENC_MTOM))
10273  {
10274  size_t l = strlen(aid) - 1;
10275  char *s = (char*)soap_malloc(soap, l);
10276  if (s)
10277  {
10278  s[0] = '<';
10279  (void)soap_strncpy(s + 1, l - 1, aid + 4, l - 3);
10280  s[l - 2] = '>';
10281  s[l - 1] = '\0';
10282  content->id = s;
10283  }
10284  }
10285  else
10286  {
10287  content->id = aid + 4;
10288  }
10289  }
10290  else
10291  {
10292  content->id = aid;
10293  }
10294  content->type = atype;
10295  content->options = aoptions;
10296  content->encoding = SOAP_MIME_BINARY;
10297  pp->mark1 = 3;
10298  }
10299  }
10300  else
10301  {
10302  pp->mark2 = 3;
10303  }
10304  return -1;
10305 }
10306 #endif
10307 
10308 /******************************************************************************/
10309 
10310 #ifndef WITH_NOIDREF
10311 static void
10313 {
10314  int i;
10315  for (i = 0; i < SOAP_IDHASH; i++)
10316  soap->iht[i] = NULL;
10317 }
10318 #endif
10319 
10320 /******************************************************************************/
10321 
10322 #ifndef WITH_NOIDREF
10323 static void
10325 {
10326  int i;
10327  struct soap_ilist *ip = NULL, *p = NULL;
10328  struct soap_flist *fp = NULL, *fq = NULL;
10329  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
10330  for (i = 0; i < SOAP_IDHASH; i++)
10331  {
10332  for (ip = soap->iht[i]; ip; ip = p)
10333  {
10334  for (fp = ip->flist; fp; fp = fq)
10335  {
10336  fq = fp->next;
10337  SOAP_FREE(soap, fp);
10338  }
10339  p = ip->next;
10340  SOAP_FREE(soap, ip);
10341  }
10342  soap->iht[i] = NULL;
10343  }
10344 }
10345 #endif
10346 
10347 /******************************************************************************/
10348 
10349 #ifndef WITH_NOIDREF
10350 SOAP_FMAC1
10351 struct soap_ilist *
10352 SOAP_FMAC2
10353 soap_lookup(struct soap *soap, const char *id)
10354 {
10355  struct soap_ilist *ip = NULL;
10356  for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
10357  if (!strcmp(ip->id, id))
10358  return ip;
10359  return NULL;
10360 }
10361 #endif
10362 
10363 /******************************************************************************/
10364 
10365 #ifndef WITH_NOIDREF
10366 SOAP_FMAC1
10367 struct soap_ilist *
10368 SOAP_FMAC2
10369 soap_enter(struct soap *soap, const char *id, int t, size_t n)
10370 {
10371  size_t h;
10372  struct soap_ilist *ip = NULL;
10373  size_t l = strlen(id);
10374  if (sizeof(struct soap_ilist) + l > l && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_ilist) + l <= SOAP_MAXALLOCSIZE))
10375  ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + l);
10376  if (ip)
10377  {
10378  ip->type = t;
10379  ip->size = n;
10380  ip->ptr = NULL;
10381  ip->spine = NULL;
10382  ip->link = NULL;
10383  ip->copy = NULL;
10384  ip->flist = NULL;
10385  ip->smart = NULL;
10386  ip->shaky = 0;
10387  (void)soap_memcpy((char*)ip->id, l + 1, id, l + 1);
10388  h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
10389  ip->next = soap->iht[h];
10390  soap->iht[h] = ip;
10391  }
10392  return ip;
10393 }
10394 #endif
10395 
10396 /******************************************************************************/
10397 
10398 SOAP_FMAC1
10399 void*
10400 SOAP_FMAC2
10401 soap_malloc(struct soap *soap, size_t n)
10402 {
10403  char *p;
10404  size_t k = n;
10405  if (SOAP_MAXALLOCSIZE > 0 && n > SOAP_MAXALLOCSIZE)
10406  {
10407  soap->error = SOAP_EOM;
10408  return NULL;
10409  }
10410  if (!soap)
10411  return SOAP_MALLOC(soap, n);
10412  n += sizeof(short);
10413  n += (~n+1) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary by rounding up */
10414  if (n + sizeof(void*) + sizeof(size_t) < k)
10415  {
10416  soap->error = SOAP_EOM;
10417  return NULL;
10418  }
10419  p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t));
10420  if (!p)
10421  {
10422  soap->error = SOAP_EOM;
10423  return NULL;
10424  }
10425  /* set a canary word to detect memory overruns and data corruption */
10426  *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
10427  /* keep chain of alloced cells for destruction */
10428  *(void**)(p + n) = soap->alist;
10429  *(size_t*)(p + n + sizeof(void*)) = n;
10430  soap->alist = p + n;
10431  return p;
10432 }
10433 
10434 /******************************************************************************/
10435 
10436 #ifdef SOAP_MEM_DEBUG
10437 static void
10438 soap_init_mht(struct soap *soap)
10439 {
10440  int i;
10441  for (i = 0; i < (int)SOAP_PTRHASH; i++)
10442  soap->mht[i] = NULL;
10443 }
10444 #endif
10445 
10446 /******************************************************************************/
10447 
10448 #ifdef SOAP_MEM_DEBUG
10449 static void
10450 soap_free_mht(struct soap *soap)
10451 {
10452  int i;
10453  struct soap_mlist *mp, *mq;
10454  for (i = 0; i < (int)SOAP_PTRHASH; i++)
10455  {
10456  for (mp = soap->mht[i]; mp; mp = mq)
10457  {
10458  mq = mp->next;
10459  if (mp->live)
10460  fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
10461  free(mp);
10462  }
10463  soap->mht[i] = NULL;
10464  }
10465 }
10466 #endif
10467 
10468 /******************************************************************************/
10469 
10470 #ifdef SOAP_MEM_DEBUG
10471 SOAP_FMAC1
10472 void*
10473 SOAP_FMAC2
10474 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
10475 {
10476  void *p = malloc(size);
10477  if (soap)
10478  {
10479  size_t h = soap_hash_ptr(p);
10480  struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
10481  if (soap->fdebug[SOAP_INDEX_TEST])
10482  {
10483  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
10484  }
10485  mp->next = soap->mht[h];
10486  mp->ptr = p;
10487  mp->file = file;
10488  mp->line = line;
10489  mp->live = 1;
10490  soap->mht[h] = mp;
10491  }
10492  return p;
10493 }
10494 #endif
10495 
10496 /******************************************************************************/
10497 
10498 #ifdef SOAP_MEM_DEBUG
10499 SOAP_FMAC1
10500 void
10501 SOAP_FMAC2
10502 soap_track_free(struct soap *soap, const char *file, int line, void *p)
10503 {
10504  if (!soap)
10505  {
10506  free(p);
10507  }
10508  else
10509  {
10510  size_t h = soap_hash_ptr(p);
10511  struct soap_mlist *mp;
10512  for (mp = soap->mht[h]; mp; mp = mp->next)
10513  if (mp->ptr == p)
10514  break;
10515  if (mp)
10516  {
10517  if (mp->live)
10518  {
10519  if (soap->fdebug[SOAP_INDEX_TEST])
10520  {
10521  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
10522  }
10523  free(p);
10524  mp->live = 0;
10525  }
10526  else
10527  {
10528  fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
10529  }
10530  }
10531  else
10532  {
10533  fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
10534  }
10535  }
10536 }
10537 #endif
10538 
10539 /******************************************************************************/
10540 
10541 #ifdef SOAP_MEM_DEBUG
10542 static void
10543 soap_track_unlink(struct soap *soap, const void *p)
10544 {
10545  size_t h = soap_hash_ptr(p);
10546  struct soap_mlist *mp;
10547  for (mp = soap->mht[h]; mp; mp = mp->next)
10548  if (mp->ptr == p)
10549  break;
10550  if (mp)
10551  mp->live = 0;
10552 }
10553 #endif
10554 
10555 /******************************************************************************/
10556 
10557 SOAP_FMAC1
10558 void
10559 SOAP_FMAC2
10560 soap_dealloc(struct soap *soap, void *p)
10561 {
10562  if (soap_check_state(soap))
10563  return;
10564  if (p)
10565  {
10566  char **q;
10567  for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q)
10568  {
10569  if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
10570  {
10571 #ifdef SOAP_MEM_DEBUG
10572  fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
10573 #endif
10574  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
10575  DBGHEX(TEST, *q - 200, 200);
10576  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
10577  soap->error = SOAP_MOE;
10578  return;
10579  }
10580  if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
10581  {
10582  *q = **(char***)q;
10583  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
10584  SOAP_FREE(soap, p);
10585  return;
10586  }
10587  }
10588  soap_delete(soap, p);
10589  }
10590  else
10591  {
10592  char *q;
10593  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
10594  while (soap->alist)
10595  {
10596  q = (char*)soap->alist;
10597  if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
10598  {
10599 #ifdef SOAP_MEM_DEBUG
10600  fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
10601 #endif
10602  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
10603  DBGHEX(TEST, q - 200, 200);
10604  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
10605  soap->error = SOAP_MOE;
10606  return;
10607  }
10608  soap->alist = *(void**)q;
10609  q -= *(size_t*)(q + sizeof(void*));
10610  SOAP_FREE(soap, q);
10611  }
10612  /* assume these were deallocated: */
10613  soap->http_content = NULL;
10614  soap->action = NULL;
10615  soap->fault = NULL;
10616  soap->header = NULL;
10617  soap->bearer = NULL;
10618  soap->userid = NULL;
10619  soap->passwd = NULL;
10620  soap->authrealm = NULL;
10621 #ifdef WITH_NTLM
10623 #endif
10624 #ifndef WITH_LEANER
10626 #endif
10627  }
10628 }
10629 
10630 /******************************************************************************/
10631 
10632 SOAP_FMAC1
10633 void
10634 SOAP_FMAC2
10635 soap_delete(struct soap *soap, void *p)
10636 {
10637  struct soap_clist **cp;
10638  if (soap_check_state(soap))
10639  return;
10640  cp = &soap->clist;
10641  if (p)
10642  {
10643  while (*cp)
10644  {
10645  if (p == (*cp)->ptr)
10646  {
10647  struct soap_clist *q = *cp;
10648  *cp = q->next;
10649  if (q->fdelete(soap, q))
10650  {
10651  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type=%d\n", q->ptr, q->type));
10652 #ifdef SOAP_MEM_DEBUG
10653  fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
10654 #endif
10655  }
10656  SOAP_FREE(soap, q);
10657  return;
10658  }
10659  cp = &(*cp)->next;
10660  }
10661  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
10662  }
10663  else
10664  {
10665  while (*cp)
10666  {
10667  struct soap_clist *q = *cp;
10668  *cp = q->next;
10669  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Delete %p type=%d (cp=%p)\n", q->ptr, q->type, (void*)q));
10670  if (q->fdelete(soap, q))
10671  {
10672  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type=%d\n", q->ptr, q->type));
10673 #ifdef SOAP_MEM_DEBUG
10674  fprintf(stderr, "new(object type=%d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
10675 #endif
10676  }
10677  SOAP_FREE(soap, q);
10678  }
10679  }
10680  soap->fault = NULL; /* assume this was deallocated */
10681  soap->header = NULL; /* assume this was deallocated */
10682 }
10683 
10684 /******************************************************************************/
10685 
10686 SOAP_FMAC1
10687 void
10688 SOAP_FMAC2
10689 soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
10690 {
10691  struct soap_clist *cp;
10692  char **q;
10693 #ifdef SOAP_MEM_DEBUG
10694  void *p;
10695  struct soap_mlist **mp, *mq;
10696  size_t h;
10697 #endif
10698  for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q)
10699  {
10700  if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
10701  {
10702 #ifdef SOAP_MEM_DEBUG
10703  fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
10704 #endif
10705  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
10706  DBGHEX(TEST, *q - 200, 200);
10707  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
10708  soap->error = SOAP_MOE;
10709  return;
10710  }
10711 #ifdef SOAP_MEM_DEBUG
10712  p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
10713  h = soap_hash_ptr(p);
10714  for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
10715  {
10716  if ((*mp)->ptr == p)
10717  {
10718  mq = *mp;
10719  *mp = mq->next;
10720  mq->next = soap_to->mht[h];
10721  soap_to->mht[h] = mq;
10722  break;
10723  }
10724  }
10725 #endif
10726  }
10727  *q = (char*)soap_to->alist;
10728  soap_to->alist = soap->alist;
10729  soap->alist = NULL;
10730 #ifdef SOAP_MEM_DEBUG
10731  cp = soap->clist;
10732  while (cp)
10733  {
10734  h = soap_hash_ptr(cp);
10735  for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
10736  {
10737  if ((*mp)->ptr == cp)
10738  {
10739  mq = *mp;
10740  *mp = mq->next;
10741  mq->next = soap_to->mht[h];
10742  soap_to->mht[h] = mq;
10743  break;
10744  }
10745  }
10746  cp = cp->next;
10747  }
10748 #endif
10749  cp = soap_to->clist;
10750  if (cp)
10751  {
10752  while (cp->next)
10753  cp = cp->next;
10754  cp->next = soap->clist;
10755  }
10756  else
10757  {
10758  soap_to->clist = soap->clist;
10759  }
10760  soap->clist = NULL;
10761 }
10762 
10763 /******************************************************************************/
10764 
10765 SOAP_FMAC1
10766 struct soap_clist *
10767 SOAP_FMAC2
10768 soap_link(struct soap *soap, int t, int n, int (*fdelete)(struct soap*, struct soap_clist*))
10769 {
10770  struct soap_clist *cp = NULL;
10771  if (soap)
10772  {
10773  if (n != SOAP_NO_LINK_TO_DELETE)
10774  {
10775  cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist));
10776  if (!cp)
10777  {
10778  soap->error = SOAP_EOM;
10779  }
10780  else
10781  {
10782  cp->next = soap->clist;
10783  cp->type = t;
10784  cp->size = n;
10785  cp->ptr = NULL;
10786  cp->fdelete = fdelete;
10787  soap->clist = cp;
10788  }
10789  }
10790  soap->alloced = t;
10791  }
10792  return cp;
10793 }
10794 
10795 /******************************************************************************/
10796 
10797 SOAP_FMAC1
10798 int
10799 SOAP_FMAC2
10800 soap_unlink(struct soap *soap, const void *p)
10801 {
10802  char **q;
10803  struct soap_clist **cp;
10804  if (soap && p)
10805  {
10806  for (q = (char**)(void*)&soap->alist; *q; q = *(char***)q)
10807  {
10808  if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
10809  {
10810  *q = **(char***)q;
10811  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
10812 #ifdef SOAP_MEM_DEBUG
10813  soap_track_unlink(soap, p);
10814 #endif
10815  return SOAP_OK; /* found and removed from dealloc chain */
10816  }
10817  }
10818  for (cp = &soap->clist; *cp; cp = &(*cp)->next)
10819  {
10820  if (p == (*cp)->ptr)
10821  {
10822  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
10823  q = (char**)*cp;
10824  *cp = (*cp)->next;
10825  SOAP_FREE(soap, q);
10826  return SOAP_OK; /* found and removed from dealloc chain */
10827  }
10828  }
10829  }
10830  return SOAP_ERR;
10831 }
10832 
10833 /******************************************************************************/
10834 
10835 #ifndef WITH_NOIDREF
10836 SOAP_FMAC1
10837 int
10838 SOAP_FMAC2
10839 soap_lookup_type(struct soap *soap, const char *id)
10840 {
10841  struct soap_ilist *ip;
10842  if (id && *id)
10843  {
10844  ip = soap_lookup(soap, id);
10845  if (ip)
10846  {
10847  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
10848  return ip->type;
10849  }
10850  }
10851  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
10852  return 0;
10853 }
10854 #endif
10855 
10856 /******************************************************************************/
10857 
10858 #ifndef WITH_NOIDREF
10859 SOAP_FMAC1
10860 short
10861 SOAP_FMAC2
10863 {
10864  short f = soap->shaky;
10865  soap->shaky = 1;
10866  return f;
10867 }
10868 #endif
10869 
10870 /******************************************************************************/
10871 
10872 #ifndef WITH_NOIDREF
10873 SOAP_FMAC1
10874 void
10875 SOAP_FMAC2
10876 soap_end_shaky(struct soap *soap, short f)
10877 {
10878  soap->shaky = f;
10879 }
10880 #endif
10881 
10882 /******************************************************************************/
10883 
10884 #ifndef WITH_NOIDREF
10885 static int
10886 soap_is_shaky(struct soap *soap, void *p)
10887 {
10888  (void)p;
10889  if (!soap->blist && !soap->shaky)
10890  return 0;
10891  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shaky %p\n", p));
10892  return 1;
10893 }
10894 #endif
10895 
10896 /******************************************************************************/
10897 
10898 #ifndef WITH_NOIDREF
10899 SOAP_FMAC1
10900 void*
10901 SOAP_FMAC2
10902 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k, int (*fbase)(int, int))
10903 {
10904  struct soap_ilist *ip;
10905  if (!p || !id || !*id)
10906  return p;
10907  ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
10908  if (!ip)
10909  {
10910  ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
10911  if (!ip)
10912  return NULL;
10913  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, (void*)p, (unsigned int)n, k));
10914  *p = NULL;
10915  if (k)
10916  {
10917  int i;
10918  if (k > SOAP_MAXPTRS)
10919  return NULL;
10920  ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*));
10921  if (!ip->spine)
10922  return NULL;
10923  ip->spine[0] = NULL;
10924  for (i = 1; i < SOAP_MAXPTRS; i++)
10925  ip->spine[i] = &ip->spine[i - 1];
10926  *p = &ip->spine[k - 1];
10927  }
10928  else
10929  {
10930  ip->link = p;
10931  ip->shaky = soap_is_shaky(soap, (void*)p);
10932  }
10933  }
10934  else if (ip->type != t && (!fbase || !fbase(ip->type, t)) && (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip)))
10935  {
10936  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup type incompatibility: ref='%s' id-type=%d ref-type=%d\n", id, ip->type, t));
10937  (void)soap_id_nullify(soap, id);
10938  return NULL;
10939  }
10940  else if (k == 0 && ip->ptr && !ip->shaky) /* when block lists are in use, ip->ptr will change */
10941  {
10942  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, ip->ptr, (unsigned int)n, k));
10943  *p = ip->ptr;
10944  }
10945  else
10946  {
10947  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes) level=%u\n", id, t, (void*)p, (unsigned int)n, k));
10948  if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip))
10949  {
10950  ip->type = t;
10951  ip->size = n;
10952  }
10953  *p = NULL;
10954  if (k)
10955  {
10956  if (!ip->spine)
10957  {
10958  int i;
10959  if (k > SOAP_MAXPTRS)
10960  return NULL;
10961  ip->spine = (void**)soap_malloc(soap, SOAP_MAXPTRS * sizeof(void*));
10962  if (!ip->spine)
10963  return NULL;
10964  ip->spine[0] = NULL;
10965  for (i = 1; i < SOAP_MAXPTRS; i++)
10966  ip->spine[i] = &ip->spine[i - 1];
10967  }
10968  *p = &ip->spine[k - 1];
10969  if (ip->ptr && !ip->shaky)
10970  ip->spine[0] = ip->ptr;
10971  }
10972  else
10973  {
10974  void *q = ip->link;
10975  ip->link = p;
10976  ip->shaky = soap_is_shaky(soap, (void*)p);
10977  *p = q;
10978  }
10979  }
10980  return p;
10981 }
10982 #endif
10983 
10984 /******************************************************************************/
10985 
10986 #ifndef WITH_NOIDREF
10987 SOAP_FMAC1
10988 void*
10989 SOAP_FMAC2
10990 soap_id_forward(struct soap *soap, const char *href, void *p, size_t i, int t, int tt, size_t n, unsigned int k, void (*finsert)(struct soap*, int, int, void*, size_t, const void*, void**), int (*fbase)(int, int))
10991 {
10992  struct soap_ilist *ip;
10993  if (!p || !href || !*href)
10994  return p;
10995  ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
10996  if (!ip)
10997  {
10998  ip = soap_enter(soap, href, t, n); /* new hash table entry for string id */
10999  if (!ip)
11000  return NULL;
11001  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, t, (unsigned long)n, k, p));
11002  }
11003  else if ((ip->type != t || ip->size != n) && k == 0)
11004  {
11005  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
11006  (void)soap_id_nullify(soap, href);
11007  return NULL;
11008  }
11009  if (finsert || n < sizeof(void*))
11010  {
11011  struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
11012  if (!fp)
11013  {
11014  soap->error = SOAP_EOM;
11015  return NULL;
11016  }
11017  if (fbase && fbase(t, ip->type) && !soap_type_punned(soap, ip))
11018  {
11019  ip->type = t;
11020  ip->size = n;
11021  }
11022  if ((ip->type != t || ip->size != n) && (!fbase || !fbase(ip->type, t)))
11023  {
11024  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forward type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
11025  SOAP_FREE(soap, fp);
11026  (void)soap_id_nullify(soap, href);
11027  return NULL;
11028  }
11029  fp->next = ip->flist;
11030  fp->type = tt;
11031  fp->ptr = p;
11032  fp->level = k;
11033  fp->index = i;
11034  fp->finsert = finsert;
11035  ip->flist = fp;
11036  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u index=%lu href='%s'\n", t, tt, (unsigned long)n, p, k, (unsigned long)i, href));
11037  }
11038  else
11039  {
11040  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, t, href));
11041  *(void**)p = ip->copy;
11042  ip->copy = p;
11043  }
11044  ip->shaky = soap_is_shaky(soap, p);
11045  return p;
11046 }
11047 #endif
11048 
11049 /******************************************************************************/
11050 
11051 SOAP_FMAC1
11052 void*
11053 SOAP_FMAC2
11054 soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*), int (*fbase)(int, int))
11055 {
11056 #ifndef WITH_NOIDREF
11057  struct soap_ilist *ip;
11058 #endif
11059  (void)id; (void)fbase;
11060  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d location=%p size=%lu\n", id, t, p, (unsigned long)n));
11061  soap->alloced = 0;
11062  if (!p)
11063  {
11064  if (finstantiate)
11065  {
11066  p = finstantiate(soap, t, type, arrayType, &n); /* soap->alloced is set in soap_link() */
11067  t = soap->alloced;
11068  }
11069  else
11070  {
11071  p = soap_malloc(soap, n);
11072  soap->alloced = t;
11073  }
11074  }
11075 #ifndef WITH_NOIDREF
11076  if (!id || !*id)
11077 #endif
11078  return p;
11079 #ifndef WITH_NOIDREF
11080  ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
11081  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup entry id='%s' for location=%p type=%d\n", id, p, t));
11082  if (!ip)
11083  {
11084  ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
11085  if (!ip)
11086  return NULL;
11087  ip->ptr = p;
11088  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu location=%p\n", id, t, (unsigned long)n, p));
11089  if (!soap->alloced)
11090  ip->shaky = soap_is_shaky(soap, p);
11091  }
11092  else if (ip->ptr)
11093  {
11094  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
11095  soap_strcpy(soap->id, sizeof(soap->id), id);
11097  return NULL;
11098  }
11099  else if ((ip->type != t && (!fbase || !fbase(t, ip->type) || soap_type_punned(soap, ip)))
11100  || (ip->type == t && ip->size != n && soap_type_punned(soap, ip)))
11101  {
11102  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter type incompatibility id='%s' expect type=%d size=%lu got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, t, (unsigned long)n));
11103  (void)soap_id_nullify(soap, id);
11104  return NULL;
11105  }
11106  else
11107  {
11108  ip->type = t;
11109  ip->size = n;
11110  ip->ptr = p;
11111  if (!soap->alloced)
11112  ip->shaky = soap_is_shaky(soap, p);
11113  if (soap->alloced || !ip->shaky)
11114  {
11115  void **q; /* ptr will not change later, so resolve links now */
11116  if (ip->spine)
11117  ip->spine[0] = p;
11118  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s' type=%d\n", ip->id, ip->type));
11119  q = (void**)ip->link;
11120  while (q)
11121  {
11122  void *r = *q;
11123  *q = p;
11124  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... link %p -> %p\n", (void*)q, p));
11125  q = (void**)r;
11126  }
11127  ip->link = NULL;
11128  }
11129  }
11130  return ip->ptr;
11131 #endif
11132 }
11133 
11134 /******************************************************************************/
11135 
11136 SOAP_FMAC1
11137 void**
11138 SOAP_FMAC2
11139 soap_id_smart(struct soap *soap, const char *id, int t, size_t n)
11140 {
11141  (void)soap; (void)id; (void)t; (void)n;
11142 #ifndef WITH_NOIDREF
11143  if (id && *id)
11144  {
11145  struct soap_ilist *ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
11146  if (!ip)
11147  {
11148  ip = soap_enter(soap, id, t, n); /* new hash table entry for string id */
11149  if (!ip)
11150  return NULL;
11151  }
11152  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New smart shared pointer entry id='%s' type=%d size=%lu smart=%p\n", id, t, (unsigned long)n, ip->smart));
11153  return &ip->smart;
11154  }
11155 #endif
11156  return NULL;
11157 }
11158 
11159 /******************************************************************************/
11160 
11161 #ifndef WITH_NOIDREF
11162 static int
11163 soap_type_punned(struct soap *soap, const struct soap_ilist *ip)
11164 {
11165  const struct soap_flist *fp;
11166  (void)soap;
11167  if (ip->ptr || ip->copy)
11168  return 1;
11169  for (fp = ip->flist; fp; fp = fp->next)
11170  if (fp->level == 0)
11171  return 1;
11172  return 0;
11173 }
11174 #endif
11175 
11176 /******************************************************************************/
11177 
11178 #ifndef WITH_NOIDREF
11179 SOAP_FMAC1
11180 int
11181 SOAP_FMAC2
11182 soap_id_nullify(struct soap *soap, const char *id)
11183 {
11184  int i;
11185  for (i = 0; i < SOAP_IDHASH; i++)
11186  {
11187  struct soap_ilist *ip;
11188  for (ip = soap->iht[i]; ip; ip = ip->next)
11189  {
11190  void *p, *q;
11191  for (p = ip->link; p; p = q)
11192  {
11193  q = *(void**)p;
11194  *(void**)p = NULL;
11195  }
11196  ip->link = NULL;
11197  }
11198  }
11199  soap_strcpy(soap->id, sizeof(soap->id), id);
11200  return soap->error = SOAP_HREF;
11201 }
11202 #endif
11203 
11204 /******************************************************************************/
11205 
11206 SOAP_FMAC1
11207 int
11208 SOAP_FMAC2
11210 {
11211 #ifndef WITH_LEANER
11212  int err;
11213  err = soap_end_attachments(soap);
11214  if (soap->dime.list)
11215  {
11216  /* SOAP body referenced attachments must appear first */
11217  soap->dime.last->next = soap->dime.first;
11218  soap->dime.first = soap->dime.list->next;
11219  soap->dime.list->next = NULL;
11220  soap->dime.last = soap->dime.list;
11221  }
11222  if (!err)
11223  err = soap_putdime(soap);
11224  if (!err)
11225  err = soap_putmime(soap);
11226  soap->mime.list = NULL;
11227  soap->mime.first = NULL;
11228  soap->mime.last = NULL;
11229  soap->dime.list = NULL;
11230  soap->dime.first = NULL;
11231  soap->dime.last = NULL;
11232  if (err)
11233  return err;
11234 #endif
11235  return soap_end_send_flush(soap);
11236 }
11237 
11238 /******************************************************************************/
11239 
11240 SOAP_FMAC1
11241 int
11242 SOAP_FMAC2
11244 {
11245  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
11246  if ((soap->mode & SOAP_IO)) /* need to flush the remaining data in buffer */
11247  {
11248  if (soap_flush(soap))
11249 #ifdef WITH_ZLIB
11250  {
11252  {
11255  }
11256  return soap->error;
11257  }
11258 #else
11259  return soap->error;
11260 #endif
11261 #ifdef WITH_ZLIB
11262  if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
11263  {
11264  int r;
11265  soap->d_stream->avail_in = 0;
11266  do
11267  {
11268  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
11269  r = deflate(soap->d_stream, Z_FINISH);
11270  if (soap->d_stream->avail_out != sizeof(soap->buf))
11271  {
11272  if (soap_flush_raw(soap, soap->z_buf, sizeof(soap->buf) - soap->d_stream->avail_out))
11273  {
11276  return soap->error;
11277  }
11278  soap->d_stream->next_out = (Byte*)soap->z_buf;
11279  soap->d_stream->avail_out = sizeof(soap->buf);
11280  }
11281  } while (r == Z_OK);
11282  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
11283  soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
11284  soap->mode &= ~SOAP_ENC_ZLIB;
11286  if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
11287  {
11288  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
11289  return soap->error = SOAP_ZLIB_ERROR;
11290  }
11291 #ifdef WITH_GZIP
11293  {
11294  soap->z_buf[0] = soap->z_crc & 0xFF;
11295  soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
11296  soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
11297  soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
11298  soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
11299  soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
11300  soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
11301  soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
11302  if (soap_flush_raw(soap, soap->z_buf, 8))
11303  return soap->error;
11304  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
11305  }
11306 #endif
11307  }
11308 #endif
11309  if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
11310  {
11311 #if !defined(__cplusplus) || defined(WITH_COMPAT)
11312  if (soap->os)
11313  {
11314  char *b = (char*)soap_push_block(soap, NULL, 1);
11315  if (b)
11316  {
11317  *b = '\0';
11318  *soap->os = soap_save_block(soap, NULL, NULL, 0);
11319  }
11320  }
11321  else
11322 #endif
11323  {
11324  char *p;
11325 #ifndef WITH_NOHTTP
11326  if (!(soap->mode & SOAP_ENC_PLAIN))
11327  {
11328  soap->mode--;
11329  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
11330  if (soap->status >= SOAP_POST)
11332  else if (soap->status != SOAP_STOP)
11334  if (soap->error || soap_flush(soap))
11335  return soap->error;
11336  soap->mode++;
11337  }
11338 #endif
11339  for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
11340  {
11341  DBGMSG(SENT, p, soap_block_size(soap, NULL));
11342  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), (int)soap->socket, soap->sendfd));
11344  if (soap->error)
11345  {
11347  return soap->error;
11348  }
11349  }
11351  }
11352 #ifndef WITH_LEANER
11354  return soap->error;
11355 #endif
11356  if ((soap->omode & SOAP_IO) == SOAP_IO_STORE && (soap->imode & SOAP_IO) != SOAP_IO_STORE)
11357  soap->omode = (soap->omode & ~SOAP_IO) | (soap->imode & SOAP_IO);
11358  }
11359 #ifndef WITH_LEANER
11360  else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
11361  {
11362  DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
11363  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", (int)soap->socket, soap->sendfd));
11364  soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7);
11365  if (soap->error)
11366  return soap->error;
11367  }
11368 #endif
11369  }
11370 #ifdef WITH_TCPFIN
11371 #if defined(WITH_OPENSSL) || defined(WITH_SYSTEMSSL)
11372  if (!soap->ssl)
11373 #endif
11375  soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
11376 #endif
11377 #if defined(__cplusplus) && !defined(WITH_COMPAT)
11378  if (soap->os)
11379  soap->os->flush();
11380 #endif
11381  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
11382  soap->omode &= ~SOAP_SEC_WSUID;
11383  soap->count = 0;
11384  soap->part = SOAP_END;
11385  return SOAP_OK;
11386 }
11387 
11388 /******************************************************************************/
11389 
11390 SOAP_FMAC1
11391 int
11392 SOAP_FMAC2
11394 {
11395  soap->part = SOAP_END;
11396 #ifndef WITH_LEAN
11397  soap->wsuid = NULL; /* reset before next send */
11398  soap->c14nexclude = NULL; /* reset before next send */
11399  soap->c14ninclude = NULL; /* reset before next send */
11400 #endif
11401 #ifndef WITH_LEANER
11402  soap->ffilterrecv = NULL;
11403  if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
11404  {
11405  soap->dime.first = NULL;
11406  soap->dime.last = NULL;
11407  return soap->error;
11408  }
11409  soap->dime.list = soap->dime.first;
11410  soap->dime.first = NULL;
11411  soap->dime.last = NULL;
11412  /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
11413  if ((soap->mode & SOAP_ENC_MIME))
11414  {
11415  if ((soap->mode & SOAP_MIME_POSTCHECK))
11416  {
11417  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n"));
11418  if (!soap->keep_alive)
11419  soap->keep_alive = -2; /* special case to keep alive */
11420 #ifndef WITH_NOIDREF
11421  soap_resolve(soap);
11422 #endif
11423  return SOAP_OK;
11424  }
11425  if (soap_getmime(soap))
11426  return soap->error;
11427  }
11428  soap->mime.list = soap->mime.first;
11429  soap->mime.first = NULL;
11430  soap->mime.last = NULL;
11431  soap->mime.boundary = NULL;
11432  if (soap->xlist)
11433  {
11434  struct soap_multipart *content;
11435  for (content = soap->mime.list; content; content = content->next)
11436  soap_resolve_attachment(soap, content);
11437  }
11438 #endif
11439  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
11440 #ifdef WITH_ZLIB
11441  if ((soap->mode & SOAP_ENC_ZLIB) && soap->d_stream)
11442  {
11443  /* Make sure end of compressed content is reached */
11444  while (soap->d_stream->next_out != Z_NULL)
11445  if ((int)soap_get1(soap) == EOF)
11446  break;
11447  soap->mode &= ~SOAP_ENC_ZLIB;
11448  (void)soap_memcpy((void*)soap->buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
11449  soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
11450  soap->buflen = soap->z_buflen;
11452  if (inflateEnd(soap->d_stream) != Z_OK)
11453  return soap->error = SOAP_ZLIB_ERROR;
11454  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
11455 #ifdef WITH_GZIP
11456  if (soap->zlib_in == SOAP_ZLIB_GZIP)
11457  {
11458  soap_wchar c;
11459  short i;
11460  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
11461  for (i = 0; i < 8; i++)
11462  {
11463  if ((int)(c = soap_get1(soap)) == EOF)
11464  {
11465  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n"));
11466  return soap->error = SOAP_ZLIB_ERROR;
11467  }
11468  soap->z_buf[i] = (char)c;
11469  }
11470  if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24)))
11471  {
11472  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
11473  return soap->error = SOAP_ZLIB_ERROR;
11474  }
11475  if (soap->d_stream->total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24)))
11476  {
11477  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n"));
11478  return soap->error = SOAP_ZLIB_ERROR;
11479  }
11480  }
11482 #endif
11483  }
11484 #endif
11485  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
11486  while ((int)soap->ahead != EOF && !soap_recv_raw(soap))
11487  continue;
11488 #ifndef WITH_NOIDREF
11489  if (soap_resolve(soap))
11490  return soap->error;
11491 #endif
11492 #ifndef WITH_LEANER
11493  if (soap->xlist)
11494  {
11495  if ((soap->mode & SOAP_ENC_MTOM))
11496  return soap->error = SOAP_MIME_HREF;
11497  return soap->error = SOAP_DIME_HREF;
11498  }
11499 #endif
11500  soap_free_ns(soap);
11501 #ifndef WITH_LEANER
11502  if (soap->fpreparefinalrecv)
11503  return soap->error = soap->fpreparefinalrecv(soap);
11504 #endif
11505  return SOAP_OK;
11506 }
11507 
11508 /******************************************************************************/
11509 
11510 SOAP_FMAC1
11511 void
11512 SOAP_FMAC2
11514 {
11515  struct soap_attribute *tp, *tq;
11516  struct Namespace *ns;
11517  soap_free_ns(soap);
11518  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
11519  while (soap->blist)
11521  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
11522  for (tp = soap->attributes; tp; tp = tq)
11523  {
11524  tq = tp->next;
11525  if (tp->value)
11526  SOAP_FREE(soap, tp->value);
11527  SOAP_FREE(soap, tp);
11528  }
11529  soap->attributes = NULL;
11530 #ifdef WITH_FAST
11531  if (soap->labbuf)
11533  soap->labbuf = NULL;
11534  soap->lablen = 0;
11535  soap->labidx = 0;
11536 #endif
11538  if (ns)
11539  {
11540  for (; ns->id; ns++)
11541  {
11542  if (ns->out)
11543  {
11544  SOAP_FREE(soap, ns->out);
11545  ns->out = NULL;
11546  }
11547  }
11550  }
11551 #ifndef WITH_LEANER
11552  while (soap->xlist)
11553  {
11554  struct soap_xlist *xp = soap->xlist->next;
11555  SOAP_FREE(soap, soap->xlist);
11556  soap->xlist = xp;
11557  }
11558 #endif
11559 #ifndef WITH_NOIDREF
11561 #endif
11563 }
11564 
11565 /******************************************************************************/
11566 
11567 static void
11569 {
11570  struct soap_nlist *np, *nq;
11571  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
11572  for (np = soap->nlist; np; np = nq)
11573  {
11574  nq = np->next;
11575  SOAP_FREE(soap, np);
11576  }
11577  soap->nlist = NULL;
11578 }
11579 
11580 /******************************************************************************/
11581 
11582 #ifdef SOAP_DEBUG
11583 static void
11584 soap_init_logs(struct soap *soap)
11585 {
11586  int i;
11587  for (i = 0; i < SOAP_MAXLOGS; i++)
11588  {
11589  soap->logfile[i] = NULL;
11590  soap->fdebug[i] = NULL;
11591  }
11592 }
11593 #endif
11594 
11595 /******************************************************************************/
11596 
11597 #ifdef SOAP_DEBUG
11598 SOAP_FMAC1
11599 void
11600 SOAP_FMAC2
11601 soap_open_logfile(struct soap *soap, int i)
11602 {
11603  if (soap->logfile[i])
11604  soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
11605 }
11606 #endif
11607 
11608 /******************************************************************************/
11609 
11610 #ifdef SOAP_DEBUG
11611 static void
11612 soap_close_logfile(struct soap *soap, int i)
11613 {
11614  if (soap->fdebug[i])
11615  {
11616  fclose(soap->fdebug[i]);
11617  soap->fdebug[i] = NULL;
11618  }
11619 }
11620 #endif
11621 
11622 /******************************************************************************/
11623 
11624 #ifdef SOAP_DEBUG
11625 SOAP_FMAC1
11626 void
11627 SOAP_FMAC2
11628 soap_close_logfiles(struct soap *soap)
11629 {
11630  int i;
11631  for (i = 0; i < SOAP_MAXLOGS; i++)
11632  soap_close_logfile(soap, i);
11633 }
11634 #endif
11635 
11636 /******************************************************************************/
11637 
11638 #ifdef SOAP_DEBUG
11639 static void
11640 soap_set_logfile(struct soap *soap, int i, const char *logfile)
11641 {
11642  const char *s;
11643  char *t = NULL;
11644  soap_close_logfile(soap, i);
11645  s = soap->logfile[i];
11646  if (s)
11648  if (logfile)
11649  {
11650  size_t l = strlen(logfile) + 1;
11651  t = (char*)SOAP_MALLOC_UNMANAGED(l);
11652  if (t)
11653  (void)soap_memcpy((void*)t, l, (const void*)logfile, l);
11654  }
11655  soap->logfile[i] = t;
11656 }
11657 #endif
11658 
11659 /******************************************************************************/
11660 
11661 SOAP_FMAC1
11662 void
11663 SOAP_FMAC2
11664 soap_set_recv_logfile(struct soap *soap, const char *logfile)
11665 {
11666  (void)soap; (void)logfile;
11667 #ifdef SOAP_DEBUG
11668  soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
11669 #endif
11670 }
11671 
11672 /******************************************************************************/
11673 
11674 SOAP_FMAC1
11675 void
11676 SOAP_FMAC2
11677 soap_set_sent_logfile(struct soap *soap, const char *logfile)
11678 {
11679  (void)soap; (void)logfile;
11680 #ifdef SOAP_DEBUG
11681  soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
11682 #endif
11683 }
11684 
11685 /******************************************************************************/
11686 
11687 SOAP_FMAC1
11688 void
11689 SOAP_FMAC2
11690 soap_set_test_logfile(struct soap *soap, const char *logfile)
11691 {
11692  (void)soap; (void)logfile;
11693 #ifdef SOAP_DEBUG
11694  soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
11695 #endif
11696 }
11697 
11698 /******************************************************************************/
11699 
11700 SOAP_FMAC1
11701 struct soap*
11702 SOAP_FMAC2
11703 soap_copy(const struct soap *soap)
11704 {
11709  soap_done(copy);
11710  if (soap_copy_context(copy, soap) != NULL)
11711  return copy;
11712  soap_free(copy);
11713  return NULL;
11714 }
11715 
11716 /******************************************************************************/
11717 
11718 SOAP_FMAC1
11719 struct soap*
11720 SOAP_FMAC2
11721 soap_copy_context(struct soap *copy, const struct soap *soap)
11722 {
11723  if (copy == soap)
11724  return copy;
11725  if (soap_check_state(soap))
11726  return NULL;
11727  if (copy)
11728  {
11729  struct soap_plugin *p = NULL;
11730  (void)soap_memcpy((void*)copy, sizeof(struct soap), (const void*)soap, sizeof(struct soap));
11731  copy->state = SOAP_COPY;
11732 #ifdef SOAP_MEM_DEBUG
11733  soap_init_mht(copy);
11734 #endif
11735 #ifdef SOAP_DEBUG
11736  soap_init_logs(copy);
11740 #endif
11741  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n"));
11742  copy->error = SOAP_OK;
11743  copy->bearer = NULL;
11744  copy->userid = NULL;
11745  copy->passwd = NULL;
11746 #ifdef WITH_NTLM
11747  copy->ntlm_challenge = NULL;
11748 #endif
11749  copy->nlist = NULL;
11750  copy->blist = NULL;
11751  copy->clist = NULL;
11752  copy->alist = NULL;
11753  copy->attributes = NULL;
11754  copy->labbuf = NULL;
11755  copy->lablen = 0;
11756  copy->labidx = 0;
11757  copy->namespaces = soap->local_namespaces;
11758  copy->local_namespaces = NULL;
11759  soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */
11760  copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */
11761  copy->c_locale = NULL;
11762 #ifdef WITH_OPENSSL
11763  copy->bio = NULL;
11764  copy->ssl = NULL;
11765  copy->session = NULL;
11766  copy->session_host[0] = '\0';
11767  copy->session_port = 443;
11768 #endif
11769 #ifdef WITH_GNUTLS
11770  copy->session = NULL;
11771 #endif
11772 #ifdef WITH_ZLIB
11773  copy->d_stream = NULL;
11774  copy->z_buf = NULL;
11775 #endif
11776 #ifndef WITH_NOIDREF
11778 #endif
11780  copy->header = NULL;
11781  copy->fault = NULL;
11782  copy->action = NULL;
11783 #ifndef WITH_LEAN
11784 #ifdef WITH_COOKIES
11785  copy->cookies = soap_copy_cookies(copy, soap);
11786 #else
11787  copy->cookies = NULL;
11788 #endif
11789 #endif
11790  copy->plugins = NULL;
11791  for (p = soap->plugins; p; p = p->next)
11792  {
11793  struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
11794  if (!q)
11795  {
11796  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not allocate plugin '%s'\n", p->id));
11797  soap_end(copy);
11798  soap_done(copy);
11799  return NULL;
11800  }
11801  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
11802  *q = *p;
11803  if (p->fcopy && (copy->error = p->fcopy(copy, q, p)) != SOAP_OK)
11804  {
11805  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s' error = %d\n", p->id, copy->error));
11806  SOAP_FREE(copy, q);
11807  soap_end(copy);
11808  soap_done(copy);
11809  return NULL;
11810  }
11811  q->next = copy->plugins;
11812  copy->plugins = q;
11813  }
11814  }
11815 #ifdef WITH_SELF_PIPE
11816  pipe(copy->pipe_fd);
11817  SOAP_SOCKNONBLOCK(copy->pipe_fd[0])
11818  SOAP_SOCKNONBLOCK(copy->pipe_fd[1])
11819 #endif
11820  return copy;
11821 }
11822 
11823 /******************************************************************************/
11824 
11825 SOAP_FMAC1
11826 void
11827 SOAP_FMAC2
11829 {
11830  struct soap_attribute *tp = NULL, *tq;
11831  if (copy == soap)
11832  return;
11833  copy->header = soap->header;
11834  copy->mode = soap->mode;
11835  copy->imode = soap->imode;
11836  copy->omode = soap->omode;
11837  copy->socket = soap->socket;
11838  copy->sendsk = soap->sendsk;
11839  copy->recvsk = soap->recvsk;
11840  copy->transfer_timeout = soap->transfer_timeout;
11841  copy->recv_maxlength = soap->recv_maxlength;
11842  copy->recv_timeout = soap->recv_timeout;
11843  copy->send_timeout = soap->send_timeout;
11844  copy->connect_timeout = soap->connect_timeout;
11845  copy->accept_timeout = soap->accept_timeout;
11846  copy->socket_flags = soap->socket_flags;
11847  copy->connect_flags = soap->connect_flags;
11848  copy->connect_retry = soap->connect_retry;
11849  copy->bind_flags = soap->bind_flags;
11850  copy->bind_inet6 = soap->bind_inet6;
11851  copy->bind_v6only = soap->bind_v6only;
11852  copy->accept_flags = soap->accept_flags;
11853  copy->sndbuf = soap->sndbuf;
11854  copy->rcvbuf = soap->rcvbuf;
11855  copy->linger_time = soap->linger_time;
11856  copy->maxlevel = soap->maxlevel;
11857  copy->maxlength = soap->maxlength;
11858  copy->maxoccurs = soap->maxoccurs;
11859  copy->os = soap->os;
11860  copy->is = soap->is;
11861  copy->sendfd = soap->sendfd;
11862  copy->recvfd = soap->recvfd;
11863  copy->bufidx = soap->bufidx;
11864  copy->buflen = soap->buflen;
11865  copy->ahead = soap->ahead;
11866  copy->cdata = soap->cdata;
11867  copy->chunksize = soap->chunksize;
11868  copy->chunkbuflen = soap->chunkbuflen;
11869  copy->keep_alive = soap->keep_alive;
11870  copy->tcp_keep_alive = soap->tcp_keep_alive;
11871  copy->tcp_keep_idle = soap->tcp_keep_idle;
11872  copy->tcp_keep_intvl = soap->tcp_keep_intvl;
11873  copy->tcp_keep_cnt = soap->tcp_keep_cnt;
11874  copy->max_keep_alive = soap->max_keep_alive;
11875 #ifndef WITH_NOIO
11876  copy->peer = soap->peer;
11877  copy->peerlen = soap->peerlen;
11878  copy->ip = soap->ip;
11879  copy->ip6[0] = soap->ip6[0];
11880  copy->ip6[1] = soap->ip6[1];
11881  copy->ip6[2] = soap->ip6[2];
11882  copy->ip6[3] = soap->ip6[3];
11883  copy->port = soap->port;
11884  (void)soap_memcpy((void*)copy->host, sizeof(copy->host), (const void*)soap->host, sizeof(soap->host));
11885  (void)soap_memcpy((void*)copy->endpoint, sizeof(copy->endpoint), (const void*)soap->endpoint, sizeof(soap->endpoint));
11886 #endif
11887 #ifdef WITH_OPENSSL
11888  copy->bio = soap->bio;
11889  copy->ctx = soap->ctx;
11890  copy->ssl = soap->ssl;
11891 #endif
11892 #ifdef WITH_GNUTLS
11893  copy->session = soap->session;
11894 #endif
11895 #ifdef WITH_SYSTEMSSL
11896  copy->ctx = soap->ctx;
11897  copy->ssl = soap->ssl;
11898 #endif
11899 #ifdef WITH_ZLIB
11900  copy->zlib_state = soap->zlib_state;
11901  copy->zlib_in = soap->zlib_in;
11902  copy->zlib_out = soap->zlib_out;
11904  {
11905  if (!copy->d_stream)
11906  copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
11907  if (copy->d_stream)
11908  (void)soap_memcpy((void*)copy->d_stream, sizeof(z_stream), (const void*)soap->d_stream, sizeof(z_stream));
11909  }
11910  copy->z_crc = soap->z_crc;
11911  copy->z_ratio_in = soap->z_ratio_in;
11912  copy->z_ratio_out = soap->z_ratio_out;
11913  copy->z_level = soap->z_level;
11914  if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
11915  {
11916  if (!copy->z_buf)
11917  copy->z_buf = (char*)SOAP_MALLOC(copy, sizeof(soap->buf));
11918  if (copy->z_buf)
11919  (void)soap_memcpy((void*)copy->z_buf, sizeof(soap->buf), (const void*)soap->z_buf, sizeof(soap->buf));
11920  else
11921  copy->z_buflen = 0;
11922  }
11923  else
11924  {
11925  copy->z_buf = NULL;
11926  copy->z_buflen = 0;
11927  }
11928  copy->z_dict = soap->z_dict;
11929  copy->z_dict_len = soap->z_dict_len;
11930 #endif
11931  (void)soap_memcpy((void*)copy->buf, sizeof(copy->buf), (const void*)soap->buf, sizeof(soap->buf));
11932  /* copy XML parser state */
11933  soap_free_ns(copy);
11935  copy->version = soap->version;
11936  if (soap->nlist && soap->local_namespaces)
11937  {
11938  struct soap_nlist *np = NULL, *nq;
11939  /* copy reversed nlist */
11940  for (nq = soap->nlist; nq; nq = nq->next)
11941  {
11942  struct soap_nlist *nr = np;
11943  size_t n = sizeof(struct soap_nlist) + strlen(nq->id);
11944  np = (struct soap_nlist*)SOAP_MALLOC(copy, n);
11945  if (!np)
11946  {
11947  np = nr;
11948  break;
11949  }
11950  (void)soap_memcpy((void*)np, n, (const void*)nq, n);
11951  np->next = nr;
11952  }
11953  while (np)
11954  {
11955  const char *s = np->ns;
11956  copy->level = np->level; /* preserve element nesting level */
11957  if (!s && np->index >= 0)
11958  {
11959  s = soap->local_namespaces[np->index].out;
11960  if (!s)
11961  s = soap->local_namespaces[np->index].ns;
11962  }
11963  if (s)
11964  (void)soap_push_namespace(copy, np->id, s);
11965  nq = np;
11966  np = np->next;
11967  SOAP_FREE(copy, nq);
11968  }
11969  }
11970  (void)soap_memcpy((void*)copy->tag, sizeof(copy->tag), (const void*)soap->tag, sizeof(soap->tag));
11971  (void)soap_memcpy((void*)copy->id, sizeof(copy->id), (const void*)soap->id, sizeof(soap->id));
11972  (void)soap_memcpy((void*)copy->href, sizeof(copy->href), (const void*)soap->href, sizeof(soap->href));
11973  (void)soap_memcpy((void*)copy->type, sizeof(copy->type), (const void*)soap->type, sizeof(soap->type));
11974  copy->other = soap->other;
11975  copy->root = soap->root;
11976  copy->null = soap->null;
11977  copy->body = soap->body;
11978  copy->part = soap->part;
11979  copy->mustUnderstand = soap->mustUnderstand;
11980  copy->level = soap->level;
11981  copy->peeked = soap->peeked;
11982  /* copy attributes */
11983  for (tq = soap->attributes; tq; tq = tq->next)
11984  {
11985  struct soap_attribute *tr = tp;
11986  size_t n = sizeof(struct soap_attribute) + strlen(tq->name);
11987  tp = (struct soap_attribute*)SOAP_MALLOC(copy, n);
11988  (void)soap_memcpy((void*)tp, n, (const void*)tq, n);
11989  if (tp->size)
11990  {
11991  tp->value = (char*)SOAP_MALLOC(copy, tp->size);
11992  if (tp->value)
11993  (void)soap_memcpy((void*)tp->value, tp->size, (const void*)tq->value, tp->size);
11994  }
11995  tp->ns = NULL;
11996  tp->next = tr;
11997  }
11998  copy->attributes = tp;
11999 }
12000 
12001 /******************************************************************************/
12002 
12003 SOAP_FMAC1
12004 void
12005 SOAP_FMAC2
12007 {
12011 #ifdef WITH_OPENSSL
12012  soap->bio = NULL;
12013  soap->ctx = NULL;
12014  soap->ssl = NULL;
12015 #endif
12016 #ifdef WITH_GNUTLS
12017  soap->xcred = NULL;
12018  soap->acred = NULL;
12019  soap->cache = NULL;
12020  soap->session = NULL;
12021  soap->dh_params = NULL;
12022  soap->rsa_params = NULL;
12023 #endif
12024 #ifdef WITH_SYSTEMSSL
12025  soap->ctx = (gsk_handle)NULL;
12026  soap->ssl = (gsk_handle)NULL;
12027 #endif
12028 #ifdef WITH_ZLIB
12029  if (soap->z_buf)
12030  SOAP_FREE(soap, soap->z_buf);
12031  soap->z_buf = NULL;
12032 #endif
12033 }
12034 
12035 /******************************************************************************/
12036 
12037 SOAP_FMAC1
12038 void
12039 SOAP_FMAC2
12041 {
12043 }
12044 
12045 /******************************************************************************/
12046 
12047 SOAP_FMAC1
12048 void
12049 SOAP_FMAC2
12051 {
12052  size_t i;
12053  soap->state = SOAP_INIT;
12054 #ifdef SOAP_MEM_DEBUG
12055  soap_init_mht(soap);
12056 #endif
12057 #ifdef SOAP_DEBUG
12058  soap_init_logs(soap);
12059 #endif
12060 #ifdef TANDEM_NONSTOP
12061  soap_set_test_logfile(soap, "TESTLOG");
12062  soap_set_sent_logfile(soap, "SENTLOG");
12063  soap_set_recv_logfile(soap, "RECVLOG");
12064 #else
12065  soap_set_test_logfile(soap, "TEST.log");
12066  soap_set_sent_logfile(soap, "SENT.log");
12067  soap_set_recv_logfile(soap, "RECV.log");
12068 #endif
12069 #ifdef WITH_SELF_PIPE
12070  pipe(soap->pipe_fd);
12071  SOAP_SOCKNONBLOCK(soap->pipe_fd[0])
12072  SOAP_SOCKNONBLOCK(soap->pipe_fd[1])
12073 #endif
12074  soap->version = 0;
12075  soap->imode = imode;
12076  soap->omode = omode;
12077  soap->mode = imode;
12078  soap->plugins = NULL;
12079  soap->user = NULL;
12080  for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++)
12081  soap->data[i] = NULL;
12082  soap->bearer = NULL;
12083  soap->userid = NULL;
12084  soap->passwd = NULL;
12085  soap->authrealm = NULL;
12086 #ifdef WITH_NTLM
12088 #endif
12089 #ifndef WITH_NOHTTP
12090  soap->fpost = http_post;
12091  soap->fget = http_get;
12092  soap->fput = http_put;
12093  soap->fpatch = http_patch;
12094  soap->fdel = http_del;
12095  soap->fopt = http_200;
12096  soap->fhead = http_200;
12097  soap->fform = NULL;
12100  soap->fparse = http_parse;
12102 #endif
12103  soap->fheader = NULL;
12104  soap->fconnect = NULL;
12105  soap->fdisconnect = NULL;
12106 #ifndef WITH_NOIO
12107  soap->ipv6_multicast_if = 0; /* in_addr_t value */
12108  soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */
12109  soap->ipv4_multicast_ttl = 0; /* 0: use default */
12110  soap->client_addr = NULL; /* client address (IPv4 or IPv6 or host name) to bind before connect, NULL for none */
12111  soap->client_addr_ipv6 = NULL; /* client address IPv6 or host name to bind before connect, NULL for none */
12112  soap->client_port = -1; /* client port to bind before connect, -1 for none */
12113  soap->client_interface = NULL; /* client interface address, NULL for none */
12114 #ifndef WITH_IPV6
12116 #else
12117  soap->fresolve = NULL;
12118 #endif
12119  soap->faccept = tcp_accept;
12120  soap->fopen = tcp_connect;
12124  soap->fsend = fsend;
12125  soap->frecv = frecv;
12126  soap->fpoll = soap_poll;
12127 #else
12128  soap->fopen = NULL;
12129  soap->fclose = NULL;
12130  soap->fpoll = NULL;
12131 #endif
12132  soap->fseterror = NULL;
12133  soap->fignore = NULL;
12134  soap->fserveloop = NULL;
12135  soap->fplugin = fplugin;
12136 #ifndef WITH_LEANER
12137  soap->fsvalidate = NULL;
12138  soap->fwvalidate = NULL;
12139  soap->feltbegin = NULL;
12140  soap->feltendin = NULL;
12141  soap->feltbegout = NULL;
12142  soap->feltendout = NULL;
12145  soap->fpreparesend = NULL;
12146  soap->fpreparerecv = NULL;
12149  soap->ffiltersend = NULL;
12150  soap->ffilterrecv = NULL;
12151  soap->fdimereadopen = NULL;
12155  soap->fdimeread = NULL;
12156  soap->fdimewrite = NULL;
12157  soap->fmimereadopen = NULL;
12161  soap->fmimeread = NULL;
12162  soap->fmimewrite = NULL;
12163 #endif
12164  soap->float_format = "%.9G"; /* Alternative: use "%G" */
12165  soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
12166  soap->long_double_format = NULL; /* Defined in custom serializer custom/long_double.c */
12167  soap->dime_id_format = "cid:id%d"; /* default DIME id format for int id index */
12168  soap->recv_maxlength = 0x7FFFFFFF; /* default max length of messages received (2GB) */
12169  soap->recv_timeout = 0;
12170  soap->send_timeout = 0;
12171  soap->transfer_timeout = 0;
12172  soap->connect_timeout = 0;
12173  soap->accept_timeout = 0;
12174  soap->socket_flags = 0;
12175  soap->connect_flags = 0;
12176  soap->connect_retry = 0;
12177  soap->bind_flags = 0;
12178 #ifdef WITH_IPV6_V6ONLY
12179  soap->bind_inet6 = 1;
12180  soap->bind_v6only = 1;
12181 #else
12182  soap->bind_inet6 = 0;
12183  soap->bind_v6only = 0;
12184 #endif
12185  soap->accept_flags = 0;
12186 #ifdef WIN32
12187  soap->sndbuf = SOAP_BUFLEN + 1; /* this size speeds up windows xfer */
12188  soap->rcvbuf = SOAP_BUFLEN + 1;
12189 #else
12190  soap->sndbuf = SOAP_BUFLEN;
12191  soap->rcvbuf = SOAP_BUFLEN;
12192 #endif
12193  soap->linger_time = 0;
12197  soap->http_version = "1.1";
12198  soap->proxy_http_version = "1.0";
12199  soap->http_content = NULL;
12201  soap->actor = NULL;
12202  soap->lang = "en";
12203  soap->keep_alive = 0;
12204  soap->tcp_keep_alive = 0;
12205  soap->tcp_keep_idle = 0;
12206  soap->tcp_keep_intvl = 0;
12207  soap->tcp_keep_cnt = 0;
12209  soap->ip = 0;
12210  soap->ip6[0] = 0;
12211  soap->ip6[1] = 0;
12212  soap->ip6[2] = 0;
12213  soap->ip6[3] = 0;
12214  soap->labbuf = NULL;
12215  soap->lablen = 0;
12216  soap->labidx = 0;
12217  soap->encodingStyle = NULL;
12218 #ifndef WITH_NONAMESPACES
12220 #else
12221  soap->namespaces = NULL;
12222 #endif
12224  soap->nlist = NULL;
12225  soap->blist = NULL;
12226  soap->clist = NULL;
12227  soap->alist = NULL;
12228  soap->shaky = 0;
12229  soap->attributes = NULL;
12230  soap->header = NULL;
12231  soap->fault = NULL;
12236  soap->os = NULL;
12237  soap->is = NULL;
12238 #ifndef WITH_LEANER
12239  soap->dom = NULL;
12240  soap->dime.list = NULL;
12241  soap->dime.first = NULL;
12242  soap->dime.last = NULL;
12243  soap->mime.list = NULL;
12244  soap->mime.first = NULL;
12245  soap->mime.last = NULL;
12246  soap->mime.boundary = NULL;
12247  soap->mime.start = NULL;
12248  soap->xlist = NULL;
12249 #endif
12250 #ifndef UNDER_CE
12251  soap->recvfd = 0;
12252  soap->sendfd = 1;
12253 #else
12254  soap->recvfd = stdin;
12255  soap->sendfd = stdout;
12256 #endif
12257  soap->tag[0] = '\0';
12258  soap->id[0] = '\0';
12259  soap->href[0] = '\0';
12260  soap->type[0] = '\0';
12261  soap->arrayType[0] = '\0';
12262  soap->arraySize[0] = '\0';
12263  soap->arrayOffset[0] = '\0';
12264  soap->endpoint[0] = '\0';
12265  soap->host[0] = '\0';
12266  soap->path[0] = '\0';
12267  soap->port = 0;
12268  soap->override_host = NULL;
12269  soap->override_port = 0;
12270  soap->action = NULL;
12271  soap->proxy_host = NULL;
12272  soap->proxy_port = 8080;
12273  soap->proxy_userid = NULL;
12274  soap->proxy_passwd = NULL;
12275  soap->proxy_from = NULL;
12276  soap->origin = NULL;
12277  soap->cors_origin = NULL;
12278  soap->cors_allow = "*";
12279  soap->cors_method = NULL;
12280  soap->cors_header = NULL;
12281  soap->cors_methods = NULL;
12282  soap->cors_headers = NULL;
12283  soap->x_frame_options = "SAMEORIGIN";
12284  soap->prolog = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
12288  soap->d_stream = NULL;
12289  soap->z_buf = NULL;
12290  soap->z_level = 6;
12291  soap->z_dict = NULL;
12292  soap->z_dict_len = 0;
12293 #ifndef WITH_LEAN
12294  soap->wsuid = NULL;
12295  soap->c14nexclude = NULL;
12296  soap->c14ninclude = NULL;
12297  soap->cookies = NULL;
12298  soap->cookie_domain = NULL;
12299  soap->cookie_path = NULL;
12300  soap->cookie_max = 32;
12301 #endif
12302 #ifdef WMW_RPM_IO
12303  soap->rpmreqid = NULL;
12304 #endif
12305 #ifndef WITH_NOIDREF
12307 #endif
12309 #ifdef WITH_OPENSSL
12310  if (!soap_ssl_init_done)
12311  soap_ssl_init();
12312  soap->fsslauth = ssl_auth_init;
12313  soap->fsslverify = NULL;
12314  soap->bio = NULL;
12315  soap->ssl = NULL;
12316  soap->ctx = NULL;
12317  soap->session = NULL;
12318  soap->session_host[0] = '\0';
12319  soap->session_port = 443;
12321  soap->keyfile = NULL;
12322  soap->keyid = NULL;
12323  soap->password = NULL;
12324  soap->cafile = NULL;
12325  soap->capath = NULL;
12326  soap->crlfile = NULL;
12327  soap->dhfile = NULL;
12328  soap->randfile = NULL;
12329 #endif
12330 #ifdef WITH_GNUTLS
12331  if (!soap_ssl_init_done)
12332  soap_ssl_init();
12333  soap->fsslauth = ssl_auth_init;
12334  soap->fsslverify = NULL;
12335  soap->xcred = NULL;
12336  soap->acred = NULL;
12337  soap->cache = NULL;
12338  soap->session = NULL;
12340  soap->keyfile = NULL;
12341  soap->keyid = NULL;
12342  soap->password = NULL;
12343  soap->cafile = NULL;
12344  soap->capath = NULL;
12345  soap->crlfile = NULL;
12346  soap->dh_params = NULL;
12347  soap->rsa_params = NULL;
12348 #endif
12349 #ifdef WITH_SYSTEMSSL
12350  soap->fsslauth = ssl_auth_init;
12351  soap->fsslverify = NULL;
12352  soap->bio = NULL;
12353  soap->ssl = (gsk_handle)NULL;
12354  soap->ctx = (gsk_handle)NULL;
12355  soap->session = NULL;
12357  soap->keyfile = NULL;
12358  soap->keyid = NULL;
12359  soap->password = NULL;
12360  soap->cafile = NULL;
12361  soap->capath = NULL;
12362  soap->crlfile = NULL;
12363  soap->dhfile = NULL;
12364  soap->randfile = NULL;
12365 #endif
12366  soap->c_locale = NULL;
12367  soap->buflen = 0;
12368  soap->bufidx = 0;
12369 #ifndef WITH_LEANER
12370  soap->dime.chunksize = 0;
12371  soap->dime.buflen = 0;
12372 #endif
12373  soap->other = 0;
12374  soap->root = -1;
12375  soap->null = 0;
12376  soap->position = 0;
12377  soap->encoding = 0;
12378  soap->mustUnderstand = 0;
12379  soap->ns = 0;
12380  soap->part = SOAP_END;
12381  soap->event = 0;
12382  soap->evlev = 0;
12383  soap->alloced = 0;
12384  soap->count = 0;
12385  soap->length = 0;
12386  soap->cdata = 0;
12387  soap->peeked = 0;
12388  soap->ahead = 0;
12389  soap->idnum = 0;
12390  soap->level = 0;
12391  soap->status = 0;
12392  soap->error = SOAP_OK;
12393  soap->errmode = 0;
12394  soap->errnum = 0;
12395 }
12396 
12397 /******************************************************************************/
12398 
12399 SOAP_FMAC1
12400 void
12401 SOAP_FMAC2
12403 {
12404  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Clean up for input/output\n"));
12405  soap->error = SOAP_OK;
12406  if (!soap->keep_alive)
12407  {
12408  soap->buflen = 0;
12409  soap->bufidx = 0;
12410  }
12411  soap->encoding = 0;
12412  soap->mode = 0;
12413  soap->part = SOAP_END;
12414  soap->peeked = 0;
12415  soap->ahead = 0;
12416  soap->level = 0;
12417  *soap->endpoint = '\0';
12420 }
12421 
12422 /******************************************************************************/
12423 
12424 SOAP_FMAC1
12425 void
12426 SOAP_FMAC2
12428 {
12429  if (soap_check_state(soap))
12430  return;
12433  while (soap->clist)
12434  {
12435  struct soap_clist *cp = soap->clist->next;
12436  SOAP_FREE(soap, soap->clist);
12437  soap->clist = cp;
12438  }
12440 #ifdef SOAP_DEBUG
12442 #endif
12443 }
12444 
12445 /******************************************************************************/
12446 
12447 SOAP_FMAC1
12448 void
12449 SOAP_FMAC2
12451 {
12454  {
12455  if (version == 1)
12456  {
12459  }
12460  else if (version == 2)
12461  {
12464  }
12465  soap->version = version;
12466  }
12467  if (version == 0)
12469  else
12470  soap->encodingStyle = NULL;
12471 }
12472 
12473 /******************************************************************************/
12474 
12475 static void
12477 {
12478  struct Namespace *p = soap->local_namespaces;
12479  if (p)
12480  {
12481  const char *ns = p[0].out;
12482  if (!ns)
12483  ns = p[0].ns;
12484  if (ns)
12485  {
12486  if (!strcmp(ns, soap_env1))
12487  {
12488  soap->version = 1; /* make sure we use SOAP 1.1 */
12489  if (p[1].out)
12490  SOAP_FREE(soap, p[1].out);
12491  p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1));
12492  if (p[1].out)
12493  (void)soap_memcpy(p[1].out, sizeof(soap_enc1), soap_enc1, sizeof(soap_enc1));
12494  }
12495  else if (!strcmp(ns, soap_env2))
12496  {
12497  soap->version = 2; /* make sure we use SOAP 1.2 */
12498  if (p[1].out)
12499  SOAP_FREE(soap, p[1].out);
12500  p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2));
12501  if (p[1].out)
12502  (void)soap_memcpy(p[1].out, sizeof(soap_enc2), soap_enc2, sizeof(soap_enc2));
12503  }
12504  }
12505  }
12506 }
12507 
12508 /******************************************************************************/
12509 
12510 SOAP_FMAC1
12511 int
12512 SOAP_FMAC2
12513 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
12514 {
12515  struct Namespace *ns = soap->local_namespaces;
12516  struct soap_nlist *np, *nq, *nr;
12517  unsigned int level = soap->level;
12518  soap->namespaces = p;
12521  /* reverse the namespace list */
12522  np = soap->nlist;
12523  soap->nlist = NULL;
12524  if (np)
12525  {
12526  nq = np->next;
12527  np->next = NULL;
12528  while (nq)
12529  {
12530  nr = nq->next;
12531  nq->next = np;
12532  np = nq;
12533  nq = nr;
12534  }
12535  }
12536  /* then push on new stack */
12537  while (np)
12538  {
12539  const char *s;
12540  soap->level = np->level; /* preserve element nesting level */
12541  s = np->ns;
12542  if (!s && np->index >= 0 && ns)
12543  {
12544  s = ns[np->index].out;
12545  if (!s)
12546  s = ns[np->index].ns;
12547  }
12548  if (s)
12549  (void)soap_push_namespace(soap, np->id, s);
12550  nq = np;
12551  np = np->next;
12552  SOAP_FREE(soap, nq);
12553  }
12554  if (ns)
12555  {
12556  int i;
12557  for (i = 0; ns[i].id; i++)
12558  {
12559  if (ns[i].out)
12560  {
12561  SOAP_FREE(soap, ns[i].out);
12562  ns[i].out = NULL;
12563  }
12564  }
12565  SOAP_FREE(soap, ns);
12566  }
12567  soap->level = level; /* restore level */
12568  return SOAP_OK;
12569 }
12570 
12571 /******************************************************************************/
12572 
12573 SOAP_FMAC1
12574 void
12575 SOAP_FMAC2
12577 {
12579  {
12580  const struct Namespace *ns1;
12581  struct Namespace *ns2;
12582  size_t n = 1;
12583  for (ns1 = soap->namespaces; ns1->id; ns1++)
12584  n++;
12585  n *= sizeof(struct Namespace);
12586  ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
12587  if (ns2)
12588  {
12589  (void)soap_memcpy((void*)ns2, n, (const void*)soap->namespaces, n);
12590  if (ns2[0].ns)
12591  {
12592  if (!strcmp(ns2[0].ns, soap_env1))
12593  soap->version = 1;
12594  else if (!strcmp(ns2[0].ns, soap_env2))
12595  soap->version = 2;
12596  }
12597  soap->local_namespaces = ns2;
12598  for (; ns2->id; ns2++)
12599  ns2->out = NULL;
12600  }
12601  }
12602 }
12603 
12604 /******************************************************************************/
12605 
12606 #ifndef WITH_LEAN
12607 SOAP_FMAC1
12608 const char *
12609 SOAP_FMAC2
12610 soap_tagsearch(const char *big, const char *little)
12611 {
12612  if (big && little)
12613  {
12614  size_t n = strlen(little);
12615  const char *s = big;
12616  while (s)
12617  {
12618  const char *t = s;
12619  size_t i;
12620  for (i = 0; i < n; i++, t++)
12621  {
12622  if (*t != little[i])
12623  break;
12624  }
12625  if (*t == '\0' || *t == ' ')
12626  {
12627  if (i == n || (i > 0 && little[i-1] == ':'))
12628  return s;
12629  }
12630  s = strchr(t, ' ');
12631  if (s)
12632  s++;
12633  }
12634  }
12635  return NULL;
12636 }
12637 #endif
12638 
12639 /******************************************************************************/
12640 
12641 SOAP_FMAC1
12642 struct soap_nlist *
12643 SOAP_FMAC2
12644 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
12645 {
12646  struct soap_nlist *np;
12647  for (np = soap->nlist; np; np = np->next)
12648  if (!strncmp(np->id, tag, n) && !np->id[n])
12649  return np;
12650  return NULL;
12651 }
12652 
12653 /******************************************************************************/
12654 
12655 #ifndef WITH_LEAN
12656 static struct soap_nlist *
12657 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly)
12658 {
12659  struct soap_nlist *np = NULL;
12660  size_t n, k;
12661  unsigned int level = soap->level + isearly;
12662  if (soap_tagsearch(soap->c14nexclude, id))
12663  return NULL;
12664  if (!utilized)
12665  {
12666  for (np = soap->nlist; np; np = np->next)
12667  {
12668  if (!strcmp(np->id, id) && ((!np->ns && *id) || (np->ns && !strcmp(np->ns, ns))))
12669  break;
12670  }
12671  if (np)
12672  {
12673  if ((np->level < level || (!np->ns && *id)) && np->index == 1)
12674  utilized = 1;
12675  else
12676  return NULL;
12677  }
12678  }
12679  else if (!*id)
12680  {
12681  for (np = soap->nlist; np; np = np->next)
12682  {
12683  if (!*np->id && np->level == level && np->index != 1)
12684  return NULL;
12685  }
12686  }
12687  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", level, id, ns ? ns : "(null)", utilized));
12688  n = strlen(id);
12689  if (ns)
12690  k = strlen(ns) + 1;
12691  else
12692  k = 0;
12693  if (sizeof(struct soap_nlist) + n + k > n && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_nlist) + n + k <= SOAP_MAXALLOCSIZE))
12694  np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
12695  if (!np)
12696  {
12697  soap->error = SOAP_EOM;
12698  return NULL;
12699  }
12700  np->next = soap->nlist;
12701  soap->nlist = np;
12702  soap_strcpy((char*)np->id, n + 1, id);
12703  if (ns)
12704  {
12705  np->ns = np->id + n + 1;
12706  soap_strcpy((char*)np->ns, k, ns);
12707  }
12708  else
12709  {
12710  np->ns = NULL;
12711  }
12712  np->level = level;
12713  np->index = utilized;
12714  return np;
12715 }
12716 #endif
12717 
12718 /******************************************************************************/
12719 
12720 #ifndef WITH_LEAN
12721 static void
12722 soap_utilize_ns(struct soap *soap, const char *tag, short isearly)
12723 {
12724  struct soap_nlist *np;
12725  size_t n = 0;
12726  if (!strncmp(tag, "xmlns:", 6))
12727  {
12728  tag += 6;
12729  n = strlen(tag);
12730  }
12731  else
12732  {
12733  const char *t = strchr(tag, ':');
12734  if (t)
12735  n = t - tag;
12736  }
12737  np = soap_lookup_ns(soap, tag, n);
12738  if (np)
12739  {
12740  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace '%s' of '%s' at level %u utilized=%d at level=%u\n", np->ns ? np->ns : "", tag, soap->level + isearly, np->index, np->level));
12741  if (np->index <= 0)
12742  {
12743  if (np->level == soap->level + isearly)
12744  np->index = 1;
12745  else
12746  (void)soap_push_ns(soap, np->id, np->ns, 1, isearly);
12747  }
12748  }
12749  else if (strncmp(tag, "xml", 3))
12750  {
12751  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing default namespace of '%s' at level %u\n", tag, soap->level + isearly));
12752  (void)soap_strncpy(soap->tag, sizeof(soap->tag), tag, n);
12753  (void)soap_push_ns(soap, soap->tag, NULL, 1, isearly);
12754  }
12755 }
12756 #endif
12757 
12758 /******************************************************************************/
12759 
12760 SOAP_FMAC1
12761 int
12762 SOAP_FMAC2
12763 soap_element(struct soap *soap, const char *tag, int id, const char *type)
12764 {
12765 #ifndef WITH_LEAN
12766  const char *s;
12767 #endif
12768  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id, type ? type : SOAP_STR_EOS));
12769 #ifdef WITH_DOM
12770 #ifndef WITH_LEAN
12771  if (soap_tagsearch(soap->wsuid, tag))
12772  {
12773  size_t i;
12774  for (s = tag, i = 0; *s && i < sizeof(soap->href) - 1; s++, i++)
12775  soap->href[i] = *s == ':' ? '-' : *s;
12776  soap->href[i] = '\0';
12777  if (soap_set_attr(soap, "wsu:Id", soap->href, 1))
12778  return soap->error;
12779  }
12780 #endif
12781 #endif
12782  soap->level++;
12783  if (soap->level > soap->maxlevel)
12784  return soap->error = SOAP_LEVEL;
12785 #ifdef WITH_DOM
12786 #ifndef WITH_LEAN
12787  if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
12788  {
12789  if (soap->evlev >= soap->level)
12790  soap->evlev = 0;
12791  if (soap->event == SOAP_SEC_BEGIN && !soap->evlev)
12792  {
12793  struct soap_nlist *np;
12794  /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
12795  for (np = soap->nlist; np; np = np->next)
12796  {
12797  int p = soap->c14ninclude ? *soap->c14ninclude == '+' || soap_tagsearch(soap->c14ninclude, np->id) != NULL : 0;
12798  if (np->index == 2 || p)
12799  {
12800  struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1, 0);
12801  if (np1 && !p)
12802  np1->index = 0;
12803  }
12804  }
12805  soap->evlev = soap->level;
12806  }
12807  }
12808 #endif
12809  if ((soap->mode & SOAP_XML_DOM))
12810  {
12811  struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
12812  if (!elt)
12813  return soap->error = SOAP_EOM;
12814  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding DOM element tag='%s' %p (parent='%s' %p)\n", tag, elt, soap->dom ? soap->dom->name : "(null)", soap->dom));
12815  elt->soap = soap;
12816  elt->next = NULL;
12817  elt->prnt = soap->dom;
12818  elt->elts = NULL;
12819  elt->atts = NULL;
12820  elt->nstr = NULL;
12821  elt->name = soap_strdup(soap, tag);
12822  elt->lead = NULL;
12823  elt->text = NULL;
12824  elt->code = NULL;
12825  elt->tail = NULL;
12826  elt->node = NULL;
12827  elt->type = 0;
12828  if (soap->dom)
12829  {
12830  struct soap_dom_element *p = soap->dom->elts;
12831  if (p)
12832  {
12833  while (p->next)
12834  p = p->next;
12835  p->next = elt;
12836  }
12837  else
12838  {
12839  soap->dom->elts = elt;
12840  }
12841  }
12842  soap->dom = elt;
12843  if (!elt->name)
12844  return soap->error = SOAP_EOM;
12845  }
12846  else
12847  {
12848 #endif
12849 #ifndef WITH_LEAN
12850  if (!soap->ns)
12851  {
12853  return soap->error;
12854  }
12855  else if ((soap->mode & SOAP_XML_INDENT))
12856  {
12857  if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
12858  return soap->error;
12859  soap->body = 1;
12860  }
12861  if ((soap->mode & SOAP_XML_DEFAULTNS))
12862  {
12863  size_t n = 0;
12864  s = strchr(tag, ':');
12865  if (s)
12866  n = s++ - tag;
12867  else
12868  s = tag;
12869  if (soap_send_raw(soap, "<", 1)
12870  || soap_send(soap, s))
12871  return soap->error;
12872  if (n)
12873  {
12874  struct Namespace *ns = soap->local_namespaces;
12875  for (; ns && ns->id; ns++)
12876  {
12877  if (*ns->id && ns->ns && !strncmp(ns->id, tag, n) && !ns->id[n])
12878  {
12879  if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && strcmp(soap->nlist->ns, ns->ns)))
12880  {
12881  (void)soap_push_ns(soap, SOAP_STR_EOS, ns->out ? ns->out : ns->ns, 0, 0);
12882  if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
12883  return soap->error;
12884  }
12885  break;
12886  }
12887  }
12888  }
12889 #ifndef WITH_NOEMPTYNAMESPACES
12890  else if (!soap->nlist || *soap->nlist->id || (soap->nlist->ns && *soap->nlist->ns))
12891  {
12892  (void)soap_push_ns(soap, SOAP_STR_EOS, SOAP_STR_EOS, 0, 0);
12893  if (soap_attribute(soap, "xmlns", SOAP_STR_EOS))
12894  return soap->error;
12895  }
12896 #endif
12897  }
12898  else
12899 #endif
12900  if (soap_send_raw(soap, "<", 1)
12901  || soap_send(soap, tag))
12902  return soap->error;
12903 #ifdef WITH_DOM
12904  }
12905 #endif
12906  if (!soap->ns)
12907  {
12908  struct Namespace *ns = soap->local_namespaces;
12909  int k = -1;
12910  if (ns)
12911  {
12912  while (k-- && ns->id)
12913  {
12914  const char *t = ns->out;
12915  if (!t)
12916  t = ns->ns;
12917  if (*ns->id && t && *t)
12918  {
12919  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(ns->id) + 6), "xmlns:%s", ns->id);
12920  if (soap_attribute(soap, soap->tmpbuf, t))
12921  return soap->error;
12922  }
12923  ns++;
12924  }
12925  }
12926  }
12927  soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
12928 #ifndef WITH_LEAN
12929  if ((soap->mode & SOAP_XML_CANONICAL))
12930  {
12931  if ((soap->mode & SOAP_XML_DEFAULTNS))
12933  else
12934  soap_utilize_ns(soap, tag, 0);
12935  }
12936 #endif
12937  if (id > 0)
12938  {
12939  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), sizeof(SOAP_BASEREFNAME) + 20), SOAP_BASEREFNAME "%d", id);
12940  if (soap->version == 2)
12941  {
12942  if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
12943  return soap->error;
12944  }
12945  else if (soap_attribute(soap, "id", soap->tmpbuf))
12946  {
12947  return soap->error;
12948  }
12949  }
12950  if (type && *type && !(soap->mode & SOAP_XML_NOTYPE))
12951  {
12952 #ifndef WITH_LEAN
12954  soap_utilize_ns(soap, type, 0);
12955 #endif
12956  if (soap_attribute(soap, "xsi:type", type))
12957  return soap->error;
12958  }
12959  if (soap->null && soap->position > 0 && soap->version == 1)
12960  {
12961  int i;
12962  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, 20), "[%d", soap->positions[0]);
12963  for (i = 1; i < soap->position; i++)
12964  {
12965  size_t l = strlen(soap->tmpbuf);
12966  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l - 1, 20), ",%d", soap->positions[i]);
12967  }
12968  soap_strcat(soap->tmpbuf, sizeof(soap->tmpbuf), "]");
12969  if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
12970  return soap->error;
12971  }
12972  if (soap->mustUnderstand)
12973  {
12974  if (soap->actor && *soap->actor)
12975  {
12976  if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
12977  return soap->error;
12978  }
12979  if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
12980  return soap->error;
12981  soap->mustUnderstand = 0;
12982  }
12983  if (soap->encoding)
12984  {
12986  {
12987  if (!*soap->encodingStyle)
12988  {
12989  if (soap->local_namespaces[1].out)
12991  else
12993  }
12994  if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
12995  return soap->error;
12996  }
12997  else
12998  {
12999  soap->encodingStyle = NULL;
13000  }
13001  soap->encoding = 0;
13002  }
13003  soap->null = 0;
13004  soap->position = 0;
13005  return SOAP_OK;
13006 }
13007 
13008 /******************************************************************************/
13009 
13010 SOAP_FMAC1
13011 int
13012 SOAP_FMAC2
13013 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
13014 {
13015  if (*tag == '-')
13016  return SOAP_OK;
13017 #ifdef WITH_DOM
13018  if (soap->feltbegout)
13019  return soap->error = soap->feltbegout(soap, tag, id, type);
13020 #endif
13021  if (soap_element(soap, tag, id, type))
13022  return soap->error;
13024 }
13025 
13026 /******************************************************************************/
13027 
13028 #if _MSC_VER < 1400 && !defined(HAVE_STRLCAT)
13029 /* concat string (truncating the result, strings must not be NULL) */
13030 SOAP_FMAC1
13031 void
13032 SOAP_FMAC2
13033 soap_strcat(char *t, size_t n, const char *s)
13034 {
13035  size_t k = strlen(t);
13036  if (k < n)
13037  {
13038  t += k;
13039  n -= k;
13040  while (--n > 0 && *s)
13041  *t++ = *s++;
13042  *t = '\0';
13043  }
13044 }
13045 #endif
13046 
13047 /******************************************************************************/
13048 
13049 #if _MSC_VER < 1400
13050 /* concat string up to m chars (leaves destination intact on overrun and returns nonzero, zero if OK) */
13051 SOAP_FMAC1
13052 int
13053 SOAP_FMAC2
13054 soap_strncat(char *t, size_t n, const char *s, size_t m)
13055 {
13056  size_t k;
13057  if (!t || !s)
13058  return 1;
13059  k = strlen(t);
13060  if (n <= k + m)
13061  return 1;
13062  t += k;
13063  n -= k;
13064  while (--n > 0 && *s)
13065  *t++ = *s++;
13066  *t = '\0';
13067  return 0;
13068 }
13069 #endif
13070 
13071 /******************************************************************************/
13072 
13073 #ifndef HAVE_STRRCHR
13074 SOAP_FMAC1
13075 char*
13076 SOAP_FMAC2
13077 soap_strrchr(const char *s, int t)
13078 {
13079  char *r = NULL;
13080  while (*s)
13081  if (*s++ == t)
13082  r = (char*)s - 1;
13083  return r;
13084 }
13085 #endif
13086 
13087 /******************************************************************************/
13088 
13089 #ifndef HAVE_STRTOL
13090 SOAP_FMAC1
13091 long
13092 SOAP_FMAC2
13093 soap_strtol(const char *s, char **t, int b)
13094 {
13095  long n = 0;
13096  int c;
13097  while (*s > 0 && *s <= 32)
13098  s++;
13099  if (b == 10)
13100  {
13101  short neg = 0;
13102  if (*s == '-')
13103  {
13104  s++;
13105  neg = 1;
13106  }
13107  else if (*s == '+')
13108  {
13109  s++;
13110  }
13111  while ((c = *s) && c >= '0' && c <= '9')
13112  {
13113  if (n >= 214748364 && (n > 214748364 || c >= '8'))
13114  {
13115  if (neg && n == 214748364 && c == '8')
13116  {
13117  if (t)
13118  *t = (char*)(s + 1);
13119  return -2147483648;
13120  }
13121  break;
13122  }
13123  n *= 10;
13124  n += c - '0';
13125  s++;
13126  }
13127  if (neg)
13128  n = -n;
13129  }
13130  else /* assume b == 16 and value is always positive */
13131  {
13132  while ((c = *s))
13133  {
13134  if (c >= '0' && c <= '9')
13135  c -= '0';
13136  else if (c >= 'A' && c <= 'F')
13137  c -= 'A' - 10;
13138  else if (c >= 'a' && c <= 'f')
13139  c -= 'a' - 10;
13140  if (n > 0x07FFFFFF)
13141  break;
13142  n <<= 4;
13143  n += c;
13144  s++;
13145  }
13146  }
13147  if (t)
13148  *t = (char*)s;
13149  return n;
13150 }
13151 #endif
13152 
13153 /******************************************************************************/
13154 
13155 #ifndef HAVE_STRTOUL
13156 SOAP_FMAC1
13157 unsigned long
13158 SOAP_FMAC2
13159 soap_strtoul(const char *s, char **t, int b)
13160 {
13161  unsigned long n = 0;
13162  int c;
13163  while (*s > 0 && *s <= 32)
13164  s++;
13165  if (b == 10)
13166  {
13167  short neg = 0;
13168  if (*s == '-')
13169  {
13170  s++;
13171  neg = 1;
13172  }
13173  else if (*s == '+')
13174  {
13175  s++;
13176  }
13177  while ((c = *s) && c >= '0' && c <= '9')
13178  {
13179  if (n >= 429496729 && (n > 429496729 || c >= '6'))
13180  break;
13181  n *= 10;
13182  n += c - '0';
13183  s++;
13184  }
13185  if (neg && n > 0)
13186  s--;
13187  }
13188  else /* b == 16 */
13189  {
13190  while ((c = *s))
13191  {
13192  if (c >= '0' && c <= '9')
13193  c -= '0';
13194  else if (c >= 'A' && c <= 'F')
13195  c -= 'A' - 10;
13196  else if (c >= 'a' && c <= 'f')
13197  c -= 'a' - 10;
13198  if (n > 0x0FFFFFFF)
13199  break;
13200  n <<= 4;
13201  n += c;
13202  s++;
13203  }
13204  }
13205  if (t)
13206  *t = (char*)s;
13207  return n;
13208 }
13209 #endif
13210 
13211 /******************************************************************************/
13212 
13213 #ifndef soap_strtoll
13214 SOAP_FMAC1
13215 LONG64
13216 SOAP_FMAC2
13217 soap_strtoll(const char *s, char **t, int b)
13218 {
13219  LONG64 n = 0LL;
13220  int c;
13221  while (*s > 0 && *s <= 32)
13222  s++;
13223  if (b == 10)
13224  {
13225  short neg = 0;
13226  if (*s == '-')
13227  {
13228  s++;
13229  neg = 1;
13230  }
13231  else if (*s == '+')
13232  {
13233  s++;
13234  }
13235  while ((c = *s) && c >= '0' && c <= '9')
13236  {
13237  if (n >= 922337203685477580LL && (n > 922337203685477580LL || c >= '8'))
13238  {
13239  if (neg && n == 922337203685477580LL && c == '8')
13240  {
13241  if (t)
13242  *t = (char*)(s + 1);
13243  return -9223372036854775807LL - 1LL; /* appease compilers that complain */
13244  }
13245  break;
13246  }
13247  n *= 10LL;
13248  n += c - '0';
13249  s++;
13250  }
13251  if (neg)
13252  n = -n;
13253  }
13254  else /* assume b == 16 and value is always positive */
13255  {
13256  while ((c = *s))
13257  {
13258  if (c >= '0' && c <= '9')
13259  c -= '0';
13260  else if (c >= 'A' && c <= 'F')
13261  c -= 'A' - 10;
13262  else if (c >= 'a' && c <= 'f')
13263  c -= 'a' - 10;
13264  if (n > 0x07FFFFFFFFFFFFFFLL)
13265  break;
13266  n <<= 4;
13267  n += c;
13268  s++;
13269  }
13270  }
13271  if (t)
13272  *t = (char*)s;
13273  return n;
13274 }
13275 #endif
13276 
13277 /******************************************************************************/
13278 
13279 #ifndef soap_strtoull
13280 SOAP_FMAC1
13281 ULONG64
13282 SOAP_FMAC2
13283 soap_strtoull(const char *s, char **t, int b)
13284 {
13285  ULONG64 n = 0UL;
13286  int c;
13287  while (*s > 0 && *s <= 32)
13288  s++;
13289  if (b == 10)
13290  {
13291  short neg = 0;
13292  if (*s == '-')
13293  {
13294  s++;
13295  neg = 1;
13296  }
13297  else if (*s == '+')
13298  {
13299  s++;
13300  }
13301  while ((c = *s) && c >= '0' && c <= '9')
13302  {
13303  if (n >= 1844674407370955161ULL && (n > 1844674407370955161ULL || c >= '6'))
13304  break;
13305  n *= 10UL;
13306  n += c - '0';
13307  s++;
13308  }
13309  if (neg && n > 0UL)
13310  s--;
13311  }
13312  else /* b == 16 */
13313  {
13314  while ((c = *s))
13315  {
13316  if (c >= '0' && c <= '9')
13317  c -= '0';
13318  else if (c >= 'A' && c <= 'F')
13319  c -= 'A' - 10;
13320  else if (c >= 'a' && c <= 'f')
13321  c -= 'a' - 10;
13322  if (n > 0x0FFFFFFFFFFFFFFFULL)
13323  break;
13324  n <<= 4;
13325  n += c;
13326  s++;
13327  }
13328  }
13329  if (t)
13330  *t = (char*)s;
13331  return n;
13332 }
13333 #endif
13334 
13335 /******************************************************************************/
13336 
13337 SOAP_FMAC1
13338 int
13339 SOAP_FMAC2
13340 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
13341 {
13342  if (!type || !*type || soap->version == 0)
13343  return soap_element_begin_out(soap, tag, id, NULL);
13344  if (soap_element(soap, tag, id, NULL))
13345  return soap->error;
13346  if (soap->version == 1)
13347  {
13348  if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
13349  return soap->error;
13350  if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
13351  return soap->error;
13352  }
13353  else
13354  {
13355  const char *s;
13356  s = strchr(type, '[');
13357  if (s && (size_t)(s - type) < sizeof(soap->tmpbuf))
13358  {
13359  (void)soap_strncpy(soap->tmpbuf, sizeof(soap->tmpbuf), type, s - type);
13360  if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
13361  return soap->error;
13362  s++;
13363  if (*s && *s != ']')
13364  {
13365  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
13366  soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0';
13367  if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf))
13368  return soap->error;
13369  }
13370  }
13371  }
13372 #ifndef WITH_LEAN
13374  soap_utilize_ns(soap, type, 0);
13375 #endif
13377 }
13378 
13379 /******************************************************************************/
13380 
13381 SOAP_FMAC1
13382 int
13383 SOAP_FMAC2
13384 soap_element_start_end_out(struct soap *soap, const char *tag)
13385 {
13386  struct soap_attribute *tp;
13387 #ifndef WITH_LEAN
13388  if ((soap->mode & SOAP_XML_CANONICAL))
13389  {
13390  struct soap_nlist *np;
13391  for (tp = soap->attributes; tp; tp = tp->next)
13392  {
13393  if (tp->visible && *tp->name && strchr(tp->name, ':'))
13394  soap_utilize_ns(soap, tp->name, 0);
13395  }
13396  if (soap->event == SOAP_SEC_BEGIN)
13397  {
13398  for (np = soap->nlist; np; np = np->next)
13399  if (soap_tagsearch(soap->c14ninclude, np->id))
13400  (void)soap_push_ns(soap, np->id, np->ns, 1, 0);
13401  soap->event = 0;
13402  soap->evlev = 0;
13403  }
13404  for (np = soap->nlist; np; np = np->next)
13405  {
13406  if (np->ns && np->index == 1)
13407  {
13408  if (*np->id)
13409  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(np->id) + 6), "xmlns:%s", np->id);
13410  else
13411  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns");
13412  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s' SEC-BEGIN=%d c14ninclude='%s'\n", np->level, soap->tmpbuf, np->ns, soap->event == SOAP_SEC_BEGIN, soap->c14ninclude ? soap->c14ninclude : "(null)"));
13413  np->index = 2;
13414  soap->level--;
13415  if (*np->id || *np->ns || soap->level > 1)
13416  if (soap_set_attr(soap, soap->tmpbuf, np->ns, 1))
13417  return soap->error;
13418  soap->level++;
13419  }
13420  else
13421  {
13422  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Binding (level=%u) %s='%s' utilized=%d\n", np->level, np->id, np->ns, np->index));
13423  }
13424  }
13425  }
13426 #endif
13427 #ifdef WITH_DOM
13428  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
13429  {
13430  struct soap_dom_attribute **att;
13431  att = &soap->dom->atts;
13432  for (tp = soap->attributes; tp; tp = tp->next)
13433  {
13434  if (tp->visible)
13435  {
13436  *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
13437  if (!*att)
13438  return soap->error;
13439  (*att)->next = NULL;
13440  (*att)->nstr = NULL;
13441  (*att)->name = soap_strdup(soap, tp->name);
13442  (*att)->text = soap_strdup(soap, tp->value);
13443  (*att)->soap = soap;
13444  if (!(*att)->name || (tp->value && !(*att)->text))
13445  return soap->error = SOAP_EOM;
13446  att = &(*att)->next;
13447  tp->visible = 0;
13448  }
13449  }
13450  return SOAP_OK;
13451  }
13452 #endif
13453  for (tp = soap->attributes; tp; tp = tp->next)
13454  {
13455  if (tp->visible)
13456  {
13457  if (soap_send_raw(soap, " ", 1) || soap_send(soap, tp->name))
13458  return soap->error;
13459  if (tp->visible == 2 && tp->value)
13460  {
13461  if (soap_send_raw(soap, "=\"", 2)
13462  || soap_string_out(soap, tp->value, tp->flag)
13463  || soap_send_raw(soap, "\"", 1))
13464  return soap->error;
13465  }
13466  else
13467  {
13468  if (soap_send_raw(soap, "=\"\"", 3))
13469  return soap->error;
13470  }
13471  tp->visible = 0;
13472  }
13473  }
13474  if (tag)
13475  {
13476 #ifndef WITH_LEAN
13477  if ((soap->mode & SOAP_XML_CANONICAL))
13478  {
13479  if (soap_send_raw(soap, ">", 1)
13480  || soap_element_end_out(soap, tag))
13481  return soap->error;
13482  return SOAP_OK;
13483  }
13484 #endif
13485  if (soap->nlist)
13487  soap->level--; /* decrement level just before /> */
13488  soap->body = 0;
13489  return soap_send_raw(soap, "/>", 2);
13490  }
13491  return soap_send_raw(soap, ">", 1);
13492 }
13493 
13494 /******************************************************************************/
13495 
13496 SOAP_FMAC1
13497 int
13498 SOAP_FMAC2
13499 soap_element_end_out(struct soap *soap, const char *tag)
13500 {
13501  if (*tag == '-')
13502  return SOAP_OK;
13503 #ifdef WITH_DOM
13504  if (soap->feltendout)
13505  return soap->error = soap->feltendout(soap, tag);
13506 #endif
13507  return soap_element_end(soap, tag);
13508 }
13509 
13510 /******************************************************************************/
13511 
13512 SOAP_FMAC1
13513 int
13514 SOAP_FMAC2
13515 soap_element_end(struct soap *soap, const char *tag)
13516 {
13517 #ifndef WITH_LEAN
13518  const char *s;
13519 #endif
13520  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
13521 #ifdef WITH_DOM
13522  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
13523  {
13524  if (soap->dom->prnt)
13525  soap->dom = soap->dom->prnt;
13526  return SOAP_OK;
13527  }
13528 #endif
13529 #ifndef WITH_LEAN
13530  if (soap->nlist)
13532  if ((soap->mode & SOAP_XML_INDENT))
13533  {
13534  if (!soap->body)
13535  {
13536  if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
13537  return soap->error;
13538  }
13539  soap->body = 0;
13540  }
13541  if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')) != NULL)
13542  tag = s + 1;
13543 #endif
13544  if (soap_send_raw(soap, "</", 2)
13545  || soap_send(soap, tag))
13546  return soap->error;
13547  soap->level--; /* decrement level just before > */
13548  return soap_send_raw(soap, ">", 1);
13549 }
13550 
13551 /******************************************************************************/
13552 
13553 SOAP_FMAC1
13554 int
13555 SOAP_FMAC2
13556 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
13557 {
13558  const char *s = "ref";
13559  int n = 1;
13560  if (soap->version == 1)
13561  {
13562  s = "href";
13563  n = 0;
13564  }
13565  else if (soap->version == 2)
13566  {
13567  s = "SOAP-ENC:ref";
13568  }
13569  (SOAP_SNPRINTF(soap->href, sizeof(soap->href), sizeof(SOAP_BASEREFNAME) + 21), "#" SOAP_BASEREFNAME "%d", href);
13570  return soap_element_href(soap, tag, id, s, soap->href + n);
13571 }
13572 
13573 /******************************************************************************/
13574 
13575 SOAP_FMAC1
13576 int
13577 SOAP_FMAC2
13578 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
13579 {
13580  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
13581  if (soap_element(soap, tag, id, NULL)
13582  || soap_attribute(soap, ref, val)
13584  return soap->error;
13585  soap->body = 0;
13586  return SOAP_OK;
13587 }
13588 
13589 /******************************************************************************/
13590 
13591 SOAP_FMAC1
13592 int
13593 SOAP_FMAC2
13594 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
13595 {
13596  struct soap_attribute *tp = NULL;
13597  for (tp = soap->attributes; tp; tp = tp->next)
13598  if (tp->visible)
13599  break;
13600  if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
13601  {
13602  if (soap_element(soap, tag, id, type)
13603  || (!tp && soap_attribute(soap, "xsi:nil", "true"))
13605  return soap->error;
13606  soap->body = 0;
13607  }
13608  else
13609  {
13610  soap->null = 1;
13611  soap->position = 0;
13612  soap->mustUnderstand = 0;
13613  }
13614  return SOAP_OK;
13615 }
13616 
13617 /******************************************************************************/
13618 
13619 SOAP_FMAC1
13620 int
13621 SOAP_FMAC2
13622 soap_element_empty(struct soap *soap, const char *tag)
13623 {
13624  if (soap_element(soap, tag, -1, NULL))
13625  return soap->error;
13626  return soap_element_start_end_out(soap, tag);
13627 }
13628 
13629 /******************************************************************************/
13630 
13631 SOAP_FMAC1
13632 int
13633 SOAP_FMAC2
13634 soap_element_nil(struct soap *soap, const char *tag)
13635 {
13636  if (soap_element(soap, tag, -1, NULL)
13637  || (soap_attribute(soap, "xsi:nil", "true")))
13638  return soap->error;
13639  return soap_element_start_end_out(soap, tag);
13640 }
13641 
13642 /******************************************************************************/
13643 
13644 SOAP_FMAC1
13645 int
13646 SOAP_FMAC2
13647 soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *type, int t, char **mark)
13648 {
13649  (void)a; (void)n;
13650  if (!p)
13651  {
13652  soap->error = soap_element_null(soap, tag, id, type);
13653  return -1;
13654  }
13655 #ifndef WITH_NOIDREF
13656  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element_id %p type=%d id=%d\n", p, t, id));
13657  if ((!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) || (soap->mode & SOAP_XML_TREE))
13658  return soap_check_and_mark(soap, p, t, mark);
13659  if (mark)
13660  *mark = NULL;
13661  if (id < -1)
13662  return soap_embed(soap, p, a, n, t);
13663  else if (id <= 0)
13664  {
13665  struct soap_plist *pp;
13666  if (a)
13667  id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
13668  else
13669  id = soap_pointer_lookup(soap, p, t, &pp);
13670  if (id)
13671  {
13672  if (soap_is_embedded(soap, pp))
13673  {
13674  soap_element_ref(soap, tag, 0, id);
13675  return -1;
13676  }
13677  if (soap_is_single(soap, pp))
13678  return 0;
13679  soap_set_embedded(soap, pp);
13680  }
13681  }
13682  return id;
13683 #else
13684  return soap_check_and_mark(soap, p, t, mark);
13685 #endif
13686 }
13687 
13688 /******************************************************************************/
13689 
13690 SOAP_FMAC1
13691 int
13692 SOAP_FMAC2
13693 soap_check_and_mark(struct soap *soap, const void *p, int t, char **mark)
13694 {
13695  if (mark)
13696  {
13697  struct soap_plist *pp;
13698  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check %p and mark %p\n", p, (void*)mark));
13699  if (!soap_pointer_lookup(soap, p, t, &pp))
13700  if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
13701  return -1;
13702  if ((soap->mode & SOAP_IO_LENGTH))
13703  {
13704  if (pp->mark1 > 0)
13705  return -1;
13706  pp->mark1 = 1;
13707  *mark = &pp->mark1;
13708  }
13709  else
13710  {
13711  if (pp->mark2 > 0)
13712  return -1;
13713  pp->mark2 = 1;
13714  *mark = &pp->mark2;
13715  }
13716  }
13717  return 0;
13718 }
13719 
13720 /******************************************************************************/
13721 
13722 SOAP_FMAC1
13723 void *
13724 SOAP_FMAC2
13725 soap_mark_lookup(struct soap *soap, const void *p, int t, struct soap_plist **ppp, char **mark)
13726 {
13727  if (!soap)
13728  return NULL;
13729  if (mark || !(soap->mode & SOAP_XML_TREE))
13730  {
13731  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark lookup %p type=%d\n", p, t));
13732  if (!soap_pointer_lookup(soap, p, t, ppp))
13733  {
13734  if (!soap_pointer_enter(soap, p, NULL, 0, t, ppp))
13735  return NULL;
13736  }
13737  else if (!(soap->mode & SOAP_XML_TREE))
13738  {
13739  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark found %p\n", (*ppp)->dup));
13740  return (*ppp)->dup;
13741  }
13742  if (mark)
13743  {
13744  if ((*ppp)->mark1 > 0)
13745  (*ppp)->mark1 = 2; /* cycle */
13746  else
13747  (*ppp)->mark1 = 1; /* cycle detection */
13748  *mark = &(*ppp)->mark1;
13749  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Mark cycle %d\n", (*ppp)->mark1));
13750  }
13751  }
13752  return NULL;
13753 }
13754 
13755 /******************************************************************************/
13756 
13757 SOAP_FMAC1
13758 int
13759 SOAP_FMAC2
13760 soap_mark_cycle(struct soap *soap, struct soap_plist *pp)
13761 {
13762  (void)soap;
13763  return pp && pp->mark1 == 2 && (soap->mode & SOAP_XML_TREE);
13764 }
13765 
13766 /******************************************************************************/
13767 
13768 SOAP_FMAC1
13769 void
13770 SOAP_FMAC2
13771 soap_mark_dup(struct soap *soap, void *a, struct soap_plist *pp)
13772 {
13773  (void)soap;
13774  if (pp)
13775  pp->dup = a;
13776 }
13777 
13778 /******************************************************************************/
13779 
13780 SOAP_FMAC1
13781 void
13782 SOAP_FMAC2
13783 soap_unmark(struct soap *soap, char *mark)
13784 {
13785  (void)soap;
13786  if (mark)
13787  *mark = 0; /* release detection */
13788 }
13789 
13790 /******************************************************************************/
13791 
13792 SOAP_FMAC1
13793 int
13794 SOAP_FMAC2
13795 soap_element_result(struct soap *soap, const char *tag)
13796 {
13797  if (soap->version == 2 && soap->encodingStyle)
13798  {
13799  if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
13800  || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
13802  || soap_string_out(soap, tag, 0)
13803  || soap_element_end_out(soap, "SOAP-RPC:result"))
13804  return soap->error;
13805  }
13806  return SOAP_OK;
13807 }
13808 
13809 /******************************************************************************/
13810 
13811 SOAP_FMAC1
13812 void
13813 SOAP_FMAC2
13814 soap_check_result(struct soap *soap, const char *tag)
13815 {
13816  (void)tag;
13817  if (soap->version == 2 && soap->encodingStyle)
13818  {
13819  soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1, NULL);
13820  /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
13821  }
13822 }
13823 
13824 /******************************************************************************/
13825 
13826 SOAP_FMAC1
13827 int
13828 SOAP_FMAC2
13829 soap_attribute(struct soap *soap, const char *name, const char *value)
13830 {
13831  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
13832 #ifdef WITH_DOM
13833  if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
13834  {
13835  struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
13836  if (!a)
13837  return soap->error;
13838  a->next = soap->dom->atts;
13839  a->nstr = NULL;
13840  a->name = soap_strdup(soap, name);
13841  a->text = soap_strdup(soap, value);
13842  a->soap = soap;
13843  soap->dom->atts = a;
13844  if (!a->name || (value && !a->text))
13845  return soap->error = SOAP_EOM;
13846  return SOAP_OK;
13847  }
13848 #endif
13849 #ifndef WITH_LEAN
13850  if ((soap->mode & SOAP_XML_CANONICAL))
13851  {
13852  /* push namespace */
13853  if (!strncmp(name, "xmlns", 5) && ((name[5] == ':') || name[5] == '\0'))
13854  {
13855  (void)soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0, 0);
13856  if (name[5] == '\0')
13858  else if (soap->c14ninclude && ((*soap->c14ninclude == '*' || soap_tagsearch(soap->c14ninclude, name + 6))))
13859  soap_utilize_ns(soap, name, 0);
13860  }
13861  else
13862  {
13863  soap->level--;
13864  if (soap_set_attr(soap, name, value, 1))
13865  return soap->error;
13866  soap->level++;
13867  }
13868  }
13869  else
13870 #endif
13871  {
13872  if (soap_send_raw(soap, " ", 1)
13873  || soap_send(soap, name))
13874  return soap->error;
13875  if (value)
13876  if (soap_send_raw(soap, "=\"", 2)
13877  || soap_string_out(soap, value, 1)
13878  || soap_send_raw(soap, "\"", 1))
13879  return soap->error;
13880  }
13881  return SOAP_OK;
13882 }
13883 
13884 /******************************************************************************/
13885 
13886 SOAP_FMAC1
13887 int
13888 SOAP_FMAC2
13889 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
13890 {
13891  if (!soap_peek_element(soap))
13892  {
13893  if (soap->other)
13894  return soap->error = SOAP_TAG_MISMATCH;
13895  if (tag && *tag == '-')
13896  return SOAP_OK;
13897  soap->error = soap_match_tag(soap, soap->tag, tag);
13898  if (!soap->error)
13899  {
13900  if (type && *soap->type && soap_match_tag(soap, soap->type, type))
13901  return soap->error = SOAP_TYPE;
13902  soap->peeked = 0;
13903  if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
13904  return soap->error = SOAP_NULL;
13905  if (soap->body)
13906  {
13907  soap->level++;
13908  if (soap->level > soap->maxlevel)
13909  return soap->error = SOAP_LEVEL;
13910  }
13911  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS));
13912  soap->error = SOAP_OK;
13913  }
13914  }
13915  else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
13916  {
13917  soap->error = SOAP_OK;
13918  }
13919  return soap->error;
13920 }
13921 
13922 /******************************************************************************/
13923 
13924 SOAP_FMAC1
13925 int
13926 SOAP_FMAC2
13927 soap_element_end_in(struct soap *soap, const char *tag)
13928 {
13929  soap_wchar c;
13930  char *s = NULL;
13931  int n = 0;
13932  if (tag && *tag == '-')
13933  return SOAP_OK;
13934  if (soap->error == SOAP_NO_TAG)
13935  soap->error = SOAP_OK;
13936 #ifdef WITH_DOM
13937  /* this whitespace or mixed content is significant for DOM "as-is" */
13938  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
13939  {
13940  const char *t = soap->dom->code; /* save XML code */
13941  s = soap_string_in(soap, -1, -1, -1, NULL);
13942  if (!soap->peeked && !s)
13943  return soap->error;
13944  if (soap->dom->prnt)
13945  soap->dom = soap->dom->prnt;
13946  if (s && (soap->mode & SOAP_XML_STRICT))
13947  {
13948  for (; *s; s++)
13949  if (!soap_coblank((soap_wchar)*s))
13950  return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */
13951  }
13952  soap->dom->code = t; /* restore XML code */
13953  }
13954 #endif
13955  if (soap->peeked)
13956  {
13957  if (*soap->tag)
13958  n++;
13959  soap->peeked = 0;
13960  }
13961  do
13962  {
13963  while (((c = soap_get(soap)) != SOAP_TT))
13964  {
13965  if ((int)c == EOF)
13966  return soap->error = SOAP_CHK_EOF;
13967  if (!soap_coblank(c))
13968  {
13969  if ((soap->mode & SOAP_XML_STRICT))
13970  return soap->error = SOAP_END_TAG; /* reject mixed content before ending tag */
13971  if (c == SOAP_LT)
13972  n++;
13973  else if (c == '/')
13974  {
13975  c = soap_get(soap);
13976  if (c == SOAP_GT && n > 0)
13977  n--;
13978  else
13979  soap_unget(soap, c);
13980  }
13981  }
13982  }
13983  } while (n-- > 0);
13984  s = soap->tag;
13985  n = sizeof(soap->tag);
13986  while ((c = soap_get(soap)) > 32)
13987  {
13988  if (n > 1)
13989  {
13990  *s++ = (char)c;
13991  n--;
13992  }
13993  }
13994  *s = '\0';
13995  if ((int)c == EOF)
13996  return soap->error = SOAP_CHK_EOF;
13997  while (soap_coblank(c))
13998  c = soap_get(soap);
13999  if (c != SOAP_GT)
14000  return soap->error = SOAP_SYNTAX_ERROR;
14001 #ifndef WITH_LEAN
14002 #ifdef WITH_DOM
14003  if (soap->feltendin)
14004  {
14005  int err = soap->error;
14006  soap->error = soap->feltendin(soap, soap->tag, tag);
14007  if (soap->error)
14008  return soap->error;
14009  if (err)
14010  return soap->error = err; /* restore error */
14011  }
14012 #endif
14013 #endif
14014  if (tag && (soap->mode & SOAP_XML_STRICT))
14015  {
14017  if (soap_match_tag(soap, soap->tag, tag))
14018  {
14019  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS));
14020  return soap->error = SOAP_SYNTAX_ERROR;
14021  }
14022  }
14023  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End tag found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS));
14024  soap->level--;
14025  return SOAP_OK;
14026 }
14027 
14028 /******************************************************************************/
14029 
14030 SOAP_FMAC1
14031 const char *
14032 SOAP_FMAC2
14033 soap_attr_value(struct soap *soap, const char *name, int flag, int occurs)
14034 {
14035  struct soap_attribute *tp;
14036  if (*name == '-')
14037  return SOAP_STR_EOS;
14038  for (tp = soap->attributes; tp; tp = tp->next)
14039  {
14040  if (tp->visible == 2 && !soap_match_att(soap, tp->name, name))
14041  break;
14042  }
14043  if (tp)
14044  {
14045  if (occurs == 4 || (occurs == 2 && (soap->mode & SOAP_XML_STRICT)))
14047  else if (flag >= 4)
14048  return soap_collapse(soap, tp->value, flag, 1);
14049  else
14050  return tp->value;
14051  }
14052  else if (occurs == 3 || (occurs == 1 && (soap->mode & SOAP_XML_STRICT)))
14053  {
14055  }
14056  else
14057  {
14058  soap->error = SOAP_OK;
14059  }
14060  return NULL;
14061 }
14062 
14063 /******************************************************************************/
14064 
14065 SOAP_FMAC1
14066 int
14067 SOAP_FMAC2
14068 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
14069 {
14070  struct soap_attribute *tp, *tq;
14071  if (*name == '-')
14072  return SOAP_OK;
14073  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS));
14074  tq = NULL;
14075  for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
14076  {
14077  if (!strcmp(tp->name, name))
14078  break;
14079  }
14080  if (!tp)
14081  {
14082  size_t l = strlen(name);
14083  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
14084  if (sizeof(struct soap_attribute) + l > l && (SOAP_MAXALLOCSIZE <= 0 || sizeof(struct soap_attribute) + l <= SOAP_MAXALLOCSIZE))
14085  tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l);
14086  if (!tp)
14087  return soap->error = SOAP_EOM;
14088  tp->ns = NULL;
14089 #ifndef WITH_LEAN
14090  if ((soap->mode & SOAP_XML_CANONICAL))
14091  {
14092  struct soap_attribute **tpp = &soap->attributes;
14093  const char *s = strchr(name, ':');
14094  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name));
14095  if (!strncmp(name, "xmlns", 5))
14096  {
14097  for (; *tpp; tpp = &(*tpp)->next)
14098  if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
14099  break;
14100  }
14101  else if (!s)
14102  {
14103  for (; *tpp; tpp = &(*tpp)->next)
14104  if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
14105  break;
14106  }
14107  else
14108  {
14109  struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
14110  if (np)
14111  {
14112  tp->ns = np->ns;
14113  }
14114  else
14115  {
14116  struct soap_attribute *tq;
14117  for (tq = soap->attributes; tq; tq = tq->next)
14118  {
14119  if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name])
14120  {
14121  tp->ns = tq->ns;
14122  break;
14123  }
14124  }
14125  }
14126  for (; *tpp; tpp = &(*tpp)->next)
14127  {
14128  int k;
14129  if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
14130  break;
14131  }
14132  }
14133  tp->next = *tpp;
14134  *tpp = tp;
14135  }
14136  else
14137 #endif
14138  if (tq)
14139  {
14140  tq->next = tp;
14141  tp->next = NULL;
14142  }
14143  else
14144  {
14145  tp->next = soap->attributes;
14146  soap->attributes = tp;
14147  }
14148  soap_strcpy((char*)tp->name, l + 1, name);
14149  tp->value = NULL;
14150  }
14151  else if (tp->visible)
14152  {
14153  return SOAP_OK;
14154  }
14155  else if (value && tp->value && tp->size <= strlen(value))
14156  {
14157  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, (void*)tp->value));
14158  SOAP_FREE(soap, tp->value);
14159  tp->value = NULL;
14160  tp->ns = NULL;
14161  }
14162  if (value)
14163  {
14164  if (!tp->value)
14165  {
14166  tp->size = strlen(value) + 1;
14167  if (SOAP_MAXALLOCSIZE <= 0 || tp->size <= SOAP_MAXALLOCSIZE)
14168  tp->value = (char*)SOAP_MALLOC(soap, tp->size);
14169  if (!tp->value)
14170  return soap->error = SOAP_EOM;
14171  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, (void*)tp->value));
14172  }
14173  soap_strcpy(tp->value, tp->size, value);
14174  if (!strncmp(tp->name, "xmlns:", 6))
14175  tp->ns = tp->value;
14176  tp->visible = 2;
14177  tp->flag = (short)flag;
14178 #ifndef WITH_LEAN
14179  if (!strcmp(name, "wsu:Id"))
14180  {
14182  soap_strcpy(soap->id, sizeof(soap->id), value);
14183  }
14185  {
14186  const char *s = strchr(name, ':');
14187  if (s && strchr(value, ':'))
14188  {
14189  struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
14190  if (np && np->ns && soap->local_namespaces)
14191  {
14192  if ((!strcmp(s + 1, "type") && !strcmp(np->ns, soap->local_namespaces[2].ns)) /* xsi:type QName */
14193  || ((!strcmp(s + 1, "arrayType") || !strcmp(s + 1, "itemType")) && !strcmp(np->ns, soap->local_namespaces[1].ns))) /* SOAP-ENC:arrayType and SOAP-ENC:itemType QName */
14194  soap_utilize_ns(soap, value, 1);
14195  }
14196  }
14197  }
14198 #endif
14199  }
14200  else
14201  {
14202  tp->visible = 1;
14203  }
14204  return SOAP_OK;
14205 }
14206 
14207 /******************************************************************************/
14208 
14209 SOAP_FMAC1
14210 void
14211 SOAP_FMAC2
14213 {
14214  struct soap_attribute *tp;
14215 #ifndef WITH_LEAN
14216  if ((soap->mode & SOAP_XML_CANONICAL))
14217  {
14218  while (soap->attributes)
14219  {
14220  tp = soap->attributes->next;
14221  if (soap->attributes->value)
14224  soap->attributes = tp;
14225  }
14226  }
14227  else
14228 #endif
14229  {
14230  for (tp = soap->attributes; tp; tp = tp->next)
14231  tp->visible = 0;
14232  }
14233 }
14234 
14235 /******************************************************************************/
14236 
14237 static int
14238 soap_getattrval(struct soap *soap, char *s, size_t *n, soap_wchar d)
14239 {
14240  char buf[8];
14241  size_t i;
14242  size_t k = *n;
14243  size_t m = 0;
14244  char *t = buf;
14245  for (i = 0; i < k; i++)
14246  {
14247  soap_wchar c;
14248  if (m)
14249  {
14250  *s++ = *t++;
14251  m--;
14252  continue;
14253  }
14254  if ((soap->mode & SOAP_C_UTFSTRING))
14255  {
14256  c = soap_get(soap);
14257  if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
14258  {
14259  t = buf;
14260  c &= 0x7FFFFFFF;
14261  if (c < 0x0800)
14262  *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
14263  else
14264  {
14265 #ifdef WITH_REPLACE_ILLEGAL_UTF8
14266  if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
14267  c = SOAP_UNKNOWN_UNICODE_CHAR;
14268 #endif
14269  if (c < 0x010000)
14270  {
14271  *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
14272  }
14273  else
14274  {
14275  if (c < 0x200000)
14276  {
14277  *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
14278  }
14279  else
14280  {
14281  if (c < 0x04000000)
14282  {
14283  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
14284  }
14285  else
14286  {
14287  *t++ = (char)(0xFC | ((c >> 30) & 0x01));
14288  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
14289  }
14290  *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
14291  }
14292  *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
14293  }
14294  *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
14295  }
14296  *t++ = (char)(0x80 | (c & 0x3F));
14297  m = t - buf - 1;
14298  if (i + m >= k)
14299  {
14300  soap_unget(soap, c | 0x80000000);
14301  *n = i;
14302  return soap->error = SOAP_EOM;
14303  }
14304  t = buf;
14305  *s++ = *t++;
14306  continue;
14307  }
14308  }
14309  else
14310  {
14311  c = soap_getutf8(soap);
14312  }
14313  switch (c)
14314  {
14315  case SOAP_TT:
14316  *s++ = '<';
14317  soap_unget(soap, '/');
14318  break;
14319  case SOAP_LT:
14320  *s++ = '<';
14321  break;
14322  case SOAP_GT:
14323  if (d == ' ')
14324  {
14325  soap_unget(soap, c);
14326  *s = '\0';
14327  *n = i + 1;
14328  return SOAP_OK;
14329  }
14330  *s++ = '>';
14331  break;
14332  case SOAP_QT:
14333  if (c == d)
14334  {
14335  *s = '\0';
14336  *n = i + 1;
14337  return SOAP_OK;
14338  }
14339  *s++ = '"';
14340  break;
14341  case SOAP_AP:
14342  if (c == d)
14343  {
14344  *s = '\0';
14345  *n = i + 1;
14346  return SOAP_OK;
14347  }
14348  *s++ = '\'';
14349  break;
14350  case '\t':
14351  case '\n':
14352  case '\r':
14353  case ' ':
14354  case '/':
14355  if (d == ' ')
14356  {
14357  soap_unget(soap, c);
14358  *s = '\0';
14359  *n = i + 1;
14360  return SOAP_OK;
14361  }
14362  *s++ = (char)c;
14363  break;
14364  default:
14365  if ((int)c == EOF)
14366  {
14367  *s = '\0';
14368  *n = i + 1;
14369  return soap->error = SOAP_CHK_EOF;
14370  }
14371  *s++ = (char)c;
14372  }
14373  }
14374  return soap->error = SOAP_EOM;
14375 }
14376 
14377 /******************************************************************************/
14378 
14379 #ifdef WITH_FAST
14380 SOAP_FMAC1
14381 int
14382 SOAP_FMAC2
14383 soap_store_lab(struct soap *soap, const char *s, size_t n)
14384 {
14385  soap->labidx = 0;
14386  return soap_append_lab(soap, s, n);
14387 }
14388 #endif
14389 
14390 /******************************************************************************/
14391 
14392 #ifdef WITH_FAST
14393 SOAP_FMAC1
14394 int
14395 SOAP_FMAC2
14396 soap_append_lab(struct soap *soap, const char *s, size_t n)
14397 {
14398  if (soap->labidx + n < soap->labidx)
14399  return soap->error = SOAP_EOM;
14400  if (soap->labidx + n >= soap->lablen)
14401  {
14402  char *t = soap->labbuf;
14403  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen));
14404  if (soap->lablen == 0)
14405  soap->lablen = SOAP_LABLEN;
14406  while (soap->labidx + n >= soap->lablen)
14407  {
14408  if (soap->lablen << 1 < soap->lablen)
14409  return soap->error = SOAP_EOM;
14410  soap->lablen <<= 1;
14411  }
14412  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen));
14414  return soap->error = SOAP_EOM;
14415  soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
14416  if (!soap->labbuf)
14417  {
14418  if (t)
14419  SOAP_FREE(soap, t);
14420  return soap->error = SOAP_EOM;
14421  }
14422  if (t)
14423  {
14424  (void)soap_memcpy((void*)soap->labbuf, soap->lablen, (const void*)t, soap->labidx);
14425  SOAP_FREE(soap, t);
14426  }
14427  }
14428  if (s)
14429  {
14430  (void)soap_memcpy((void*)(soap->labbuf + soap->labidx), soap->lablen - soap->labidx, (const void*)s, n);
14431  soap->labidx += n;
14432  }
14433  return SOAP_OK;
14434 }
14435 #endif
14436 
14437 /******************************************************************************/
14438 
14439 SOAP_FMAC1
14440 int
14441 SOAP_FMAC2
14443 {
14444 #ifdef WITH_DOM
14445  struct soap_dom_attribute **att = NULL;
14446  char *lead = NULL;
14447 #endif
14448  struct soap_attribute *tp, *tq = NULL;
14449  const char *t;
14450  char *s;
14451  soap_wchar c;
14452  int i;
14453  if (soap->peeked)
14454  {
14455  if (!*soap->tag)
14456  return soap->error = SOAP_NO_TAG;
14457  return SOAP_OK;
14458  }
14459  soap->peeked = 1;
14460  soap->id[0] = '\0';
14461  soap->href[0] = '\0';
14462  soap->type[0] = '\0';
14463  soap->arrayType[0] = '\0';
14464  soap->arraySize[0] = '\0';
14465  soap->arrayOffset[0] = '\0';
14466  soap->other = 0;
14467  soap->root = -1;
14468  soap->position = 0;
14469  soap->null = 0;
14470  soap->mustUnderstand = 0;
14471  /* UTF-8 BOM? */
14472  c = soap_getchar(soap);
14473  if (c == 0xEF && soap_get0(soap) == 0xBB)
14474  {
14475  soap_get1(soap);
14476  c = soap_get1(soap);
14477  if (c == 0xBF)
14478  soap->mode &= ~SOAP_ENC_LATIN;
14479  else
14480  soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */
14481  }
14482  else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
14483  || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
14484  {
14485  return soap->error = SOAP_UTF_ERROR;
14486  }
14487  else
14488  {
14489  soap_unget(soap, c);
14490  }
14491  c = soap_get(soap);
14492 #ifdef WITH_DOM
14493  /* whitespace leading up to the start tag is significant for DOM as-is (but comments and PIs are removed from this lead) */
14494  if (soap_coblank(c))
14495  {
14496  soap->labidx = 0;
14497  do
14498  {
14499  if (soap_append_lab(soap, NULL, 0))
14500  return soap->error;
14501  s = soap->labbuf + soap->labidx;
14502  i = soap->lablen - soap->labidx;
14503  soap->labidx = soap->lablen;
14504  while (soap_coblank(c) && i-- > 0)
14505  {
14506  *s++ = c;
14507  c = soap_get(soap);
14508  }
14509  } while (soap_coblank(c) || i == 0);
14510  *s = '\0';
14511  lead = soap->labbuf;
14512  }
14513 #else
14514  /* skip space */
14515  while (soap_coblank(c))
14516  c = soap_get(soap);
14517 #endif
14518  if (c != SOAP_LT)
14519  {
14520  *soap->tag = '\0';
14521  if ((int)c == EOF)
14522  return soap->error = SOAP_CHK_EOF;
14523  soap_unget(soap, c);
14524 #ifdef WITH_DOM
14525  /* whitespace leading up to the end tag is significant for DOM as-is */
14526  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
14527  {
14528  if (lead && *lead)
14529  soap->dom->tail = soap_strdup(soap, lead);
14530  else
14531  soap->dom->tail = SOAP_STR_EOS; /* body with closing tag instead of <tag/> */
14532  }
14533 #endif
14534  return soap->error = SOAP_NO_TAG;
14535  }
14536  do
14537  {
14538  c = soap_get1(soap);
14539  } while (soap_coblank(c));
14540  s = soap->tag;
14541  i = sizeof(soap->tag);
14542  while (c != '>' && c != '/' && c > 32 && (int)c != EOF)
14543  {
14544  if (i > 1)
14545  {
14546  *s++ = (char)c;
14547  i--;
14548  }
14549  c = soap_get1(soap);
14550  }
14551  *s = '\0';
14552  while (soap_coblank(c))
14553  c = soap_get1(soap);
14554 #ifdef WITH_DOM
14555  if ((soap->mode & SOAP_XML_DOM))
14556  {
14557  struct soap_dom_element *elt;
14558  elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
14559  if (!elt)
14560  return soap->error;
14561  elt->next = NULL;
14562  elt->prnt = soap->dom;
14563  elt->elts = NULL;
14564  elt->atts = NULL;
14565  elt->nstr = NULL;
14566  elt->name = soap_strdup(soap, soap->tag);
14567  elt->text = NULL;
14568  elt->code = NULL;
14569  elt->tail = NULL;
14570  elt->node = NULL;
14571  elt->type = 0;
14572  if (lead && *lead)
14573  elt->lead = soap_strdup(soap, lead);
14574  else
14575  elt->lead = NULL;
14576  elt->soap = soap;
14577  if (soap->dom)
14578  {
14579  struct soap_dom_element *p = soap->dom->elts;
14580  if (p)
14581  {
14582  while (p->next)
14583  p = p->next;
14584  p->next = elt;
14585  }
14586  else
14587  {
14588  soap->dom->elts = elt;
14589  }
14590  }
14591  soap->dom = elt;
14592  att = &elt->atts;
14593  if (!elt->name)
14594  return soap->error = SOAP_EOM;
14595  }
14596 #endif
14598  for (tp = soap->attributes; tp; tp = tp->next)
14599  tp->visible = 0;
14600  while ((int)c != EOF && c != '>' && c != '/')
14601  {
14602  s = soap->tmpbuf;
14603  i = sizeof(soap->tmpbuf);
14604  while (c != '=' && c != '>' && c != '/' && c > 32 && (int)c != EOF)
14605  {
14606  if (i > 1)
14607  {
14608  *s++ = (char)c;
14609  i--;
14610  }
14611  c = soap_get1(soap);
14612  }
14613  *s = '\0';
14614  if (i == sizeof(soap->tmpbuf))
14615  return soap->error = SOAP_SYNTAX_ERROR;
14616 #ifdef WITH_DOM
14617  /* add attribute name to dom */
14618  if (att)
14619  {
14620  *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
14621  if (!*att)
14622  return soap->error;
14623  (*att)->next = NULL;
14624  (*att)->nstr = NULL;
14625  (*att)->name = soap_strdup(soap, soap->tmpbuf);
14626  (*att)->text = NULL;
14627  (*att)->soap = soap;
14628  if (!(*att)->name)
14629  return soap->error = SOAP_EOM;
14630  }
14631 #endif
14632  if (!strncmp(soap->tmpbuf, "xmlns", 5))
14633  {
14634  if (soap->tmpbuf[5] == ':')
14635  t = soap->tmpbuf + 6;
14636  else if (soap->tmpbuf[5])
14637  t = NULL;
14638  else
14639  t = SOAP_STR_EOS;
14640  }
14641  else
14642  {
14643  t = NULL;
14644  }
14645  tq = NULL;
14646  for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
14647  {
14648  if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
14649  break;
14650  }
14651  if (!tp)
14652  {
14653  size_t l = strlen(soap->tmpbuf);
14654  tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + l);
14655  if (!tp)
14656  return soap->error = SOAP_EOM;
14657  (void)soap_memcpy((char*)tp->name, l + 1, soap->tmpbuf, l + 1);
14658  tp->value = NULL;
14659  tp->size = 0;
14660  tp->ns = NULL;
14661  tp->visible = 0;
14662  /* append attribute to the end of the list */
14663  if (tq)
14664  {
14665  tq->next = tp;
14666  tp->next = NULL;
14667  }
14668  else
14669  {
14670  tp->next = soap->attributes;
14671  soap->attributes = tp;
14672  }
14673  }
14674  while (soap_coblank(c))
14675  c = soap_get1(soap);
14676  if (c == '=')
14677  {
14678  size_t k;
14679  do
14680  {
14681  c = soap_getutf8(soap);
14682  } while (soap_coblank(c));
14683  if (c != SOAP_QT && c != SOAP_AP)
14684  {
14685  soap_unget(soap, c);
14686  c = ' '; /* blank delimiter */
14687  }
14688  k = tp->size;
14689  if (soap_getattrval(soap, tp->value, &k, c))
14690  {
14691 #ifdef WITH_FAST
14692  if (soap->error != SOAP_EOM)
14693  return soap->error;
14694  soap->error = SOAP_OK;
14695  if (soap_store_lab(soap, tp->value, k))
14696  return soap->error;
14697  if (tp->value)
14698  SOAP_FREE(soap, tp->value);
14699  tp->value = NULL;
14700  for (;;)
14701  {
14702  k = soap->lablen - soap->labidx;
14703  if (soap_getattrval(soap, soap->labbuf + soap->labidx, &k, c))
14704  {
14705  if (soap->error != SOAP_EOM)
14706  return soap->error;
14707  soap->error = SOAP_OK;
14708  soap->labidx = soap->lablen;
14709  if (soap_append_lab(soap, NULL, 0))
14710  return soap->error;
14711  }
14712  else
14713  {
14714  break;
14715  }
14716  }
14717  if (soap->labidx)
14718  {
14719  tp->size = soap->lablen;
14720  }
14721  else
14722  {
14723  tp->size = strlen(soap->labbuf) + 1;
14724  if (tp->size < SOAP_LABLEN)
14725  tp->size = SOAP_LABLEN;
14726  }
14727  tp->value = (char*)SOAP_MALLOC(soap, tp->size);
14728  if (!tp->value)
14729  return soap->error = SOAP_EOM;
14730  soap_strcpy(tp->value, tp->size, soap->labbuf);
14731 #else
14732  tp->size = k;
14733  if (soap->error != SOAP_EOM)
14734  return soap->error;
14735  soap->error = SOAP_OK;
14736  if (soap_alloc_block(soap) == NULL)
14737  return soap->error;
14738  for (;;)
14739  {
14740  s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
14741  if (!s)
14742  return soap->error;
14743  k = SOAP_BLKLEN;
14744  if (soap_getattrval(soap, s, &k, c))
14745  {
14746  if (soap->error != SOAP_EOM)
14747  return soap->error;
14748  soap->error = SOAP_OK;
14749  soap_size_block(soap, NULL, k);
14750  }
14751  else
14752  {
14753  break;
14754  }
14755  }
14756  k = tp->size + soap->blist->size;
14757  if (SOAP_MAXALLOCSIZE > 0 && k > SOAP_MAXALLOCSIZE)
14758  return soap->error = SOAP_EOM;
14759  s = (char*)SOAP_MALLOC(soap, k);
14760  if (!s)
14761  return soap->error = SOAP_EOM;
14762  if (tp->value)
14763  {
14764  (void)soap_memcpy((void*)s, k, (const void*)tp->value, tp->size);
14765  SOAP_FREE(soap, tp->value);
14766  }
14767  soap_save_block(soap, NULL, s + tp->size, 0);
14768  tp->value = s;
14769  tp->size = k;
14770 #endif
14771  }
14772  if (tp->visible)
14773  {
14774  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Duplicate attribute in %s\n", soap->tag));
14775  return soap->error = SOAP_SYNTAX_ERROR; /* redefined (duplicate) attribute */
14776  }
14777  tp->visible = 2; /* seen this attribute w/ value */
14778  do
14779  {
14780  c = soap_get1(soap);
14781  } while (soap_coblank(c));
14782 #ifdef WITH_DOM
14783  if (att && tp->value)
14784  {
14785  (*att)->text = soap_strdup(soap, tp->value);
14786  if (!(*att)->text)
14787  return soap->error = SOAP_EOM;
14788  }
14789 #endif
14790  }
14791  else
14792  {
14793  tp->visible = 1; /* seen this attribute w/o value */
14794  }
14795 #ifdef WITH_DOM
14796  if (att)
14797  att = &(*att)->next;
14798 #endif
14799  if (t && tp->value)
14800  {
14801  if (soap_push_namespace(soap, t, tp->value) == NULL)
14802  return soap->error;
14803  }
14804  }
14805 #ifdef WITH_DOM
14806  if (att)
14807  {
14809  for (att = &soap->dom->atts; *att; att = &(*att)->next)
14810  (*att)->nstr = soap_current_namespace_att(soap, (*att)->name);
14811  }
14812 #endif
14813  if ((int)c == EOF)
14814  return soap->error = SOAP_CHK_EOF;
14815  soap->body = (c != '/');
14816  if (!soap->body)
14817  {
14818  do
14819  {
14820  c = soap_get1(soap);
14821  } while (soap_coblank(c));
14822  }
14823 #ifdef WITH_DOM
14824  if ((soap->mode & SOAP_XML_DOM))
14825  {
14826  if (!soap->body && soap->dom->prnt)
14827  soap->dom = soap->dom->prnt;
14828  }
14829 #endif
14830  for (tp = soap->attributes; tp; tp = tp->next)
14831  {
14832  if (tp->visible && tp->value)
14833  {
14834 #ifndef WITH_NOIDREF
14835  if (!strcmp(tp->name, "id"))
14836  {
14837  if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE))
14838  || (soap->mode & SOAP_XML_GRAPH))
14839  {
14840  *soap->id = '#';
14841  soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value);
14842  }
14843  }
14844  else if (!strcmp(tp->name, "href"))
14845  {
14846  if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE))
14847  || (soap->mode & SOAP_XML_GRAPH)
14848  || ((soap->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#'))
14849  soap_strcpy(soap->href, sizeof(soap->href), tp->value);
14850  }
14851  else if (!strcmp(tp->name, "ref"))
14852  {
14853  if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE))
14854  || (soap->mode & SOAP_XML_GRAPH))
14855  {
14856  *soap->href = '#';
14857  soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value);
14858  }
14859  }
14860 #else
14861  if (!strcmp(tp->name, "href"))
14862  {
14863  if ((soap->mode & (SOAP_ENC_MTOM | SOAP_ENC_DIME)) && *tp->value != '#')
14864  soap_strcpy(soap->href, sizeof(soap->href), tp->value);
14865  }
14866 #endif
14867  else if (!soap_match_tag(soap, tp->name, "xsi:type"))
14868  {
14869  soap_strcpy(soap->type, sizeof(soap->type), tp->value);
14870  }
14871  else if ((!soap_match_tag(soap, tp->name, "xsi:null")
14872  || !soap_match_tag(soap, tp->name, "xsi:nil"))
14873  && (!strcmp(tp->value, "1")
14874  || !strcmp(tp->value, "true")))
14875  {
14876  soap->null = 1;
14877  }
14878  else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:encodingStyle"))
14879  {
14880  if (!soap->encodingStyle)
14882  soap_version(soap);
14883  }
14884  else if (soap->version == 1)
14885  {
14886  if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
14887  {
14888  s = soap_strrchr(tp->value, '[');
14889  if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
14890  {
14891  (void)soap_strncpy(soap->arrayType, sizeof(soap->arrayType), tp->value, s - tp->value);
14892  soap_strcpy(soap->arraySize, sizeof(soap->arraySize), s);
14893  }
14894  else
14895  soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value);
14896  }
14897  else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
14898  {
14899  soap_strcpy(soap->arrayOffset, sizeof(soap->arrayOffset), tp->value);
14900  }
14901  else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
14902  {
14904  }
14905  else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
14906  {
14907  soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
14908  }
14909  else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
14910  && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
14911  {
14912  soap->mustUnderstand = 1;
14913  }
14914  else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
14915  {
14916  if ((!soap->actor || strcmp(soap->actor, tp->value))
14917  && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
14918  soap->other = 1;
14919  }
14920  }
14921  else if (soap->version == 2)
14922  {
14923 #ifndef WITH_NOIDREF
14924  if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id"))
14925  {
14926  *soap->id = '#';
14927  soap_strcpy(soap->id + 1, sizeof(soap->id) - 1, tp->value);
14928  }
14929  else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
14930  {
14931  *soap->href = '#';
14932  soap_strcpy(soap->href + (*tp->value != '#'), sizeof(soap->href) - 1, tp->value);
14933  }
14934  else
14935 #endif
14936  if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
14937  {
14938  soap_strcpy(soap->arrayType, sizeof(soap->arrayType), tp->value);
14939  }
14940  else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
14941  {
14942  soap_strcpy(soap->arraySize, sizeof(soap->arraySize), tp->value);
14943  }
14944  else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
14945  && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
14946  {
14947  soap->mustUnderstand = 1;
14948  }
14949  else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
14950  {
14951  if ((!soap->actor || strcmp(soap->actor, tp->value))
14952  && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
14953  soap->other = 1;
14954  }
14955  }
14956  else
14957  {
14958  if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
14959  soap->mustUnderstand = 1;
14960  }
14961  }
14962  }
14963 #ifdef WITH_DOM
14964  if (soap->feltbegin)
14965  return soap->error = soap->feltbegin(soap, soap->tag);
14966 #endif
14967  return soap->error = SOAP_OK;
14968 }
14969 
14970 /******************************************************************************/
14971 
14972 SOAP_FMAC1
14973 void
14974 SOAP_FMAC2
14976 {
14977  soap->error = SOAP_OK;
14978  soap_revert(soap);
14979 }
14980 
14981 /******************************************************************************/
14982 
14983 SOAP_FMAC1
14984 void
14985 SOAP_FMAC2
14987 {
14988  if (!soap->peeked)
14989  {
14990  soap->peeked = 1;
14991  if (soap->body)
14992  soap->level--;
14993  }
14994  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level));
14995 }
14996 
14997 /******************************************************************************/
14998 
14999 SOAP_FMAC1
15000 int
15001 SOAP_FMAC2
15003 {
15004  int n = 0;
15005  soap_wchar c;
15006  soap->level++;
15007  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Ignoring XML content at level=%u\n", soap->level));
15008 #ifdef WITH_DOM
15009  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
15010  {
15011  if (!soap_string_in(soap, -1, -1, -1, NULL))
15012  return soap->error;
15013  }
15014  else
15015 #endif
15016  {
15017  for (;;)
15018  {
15019  c = soap_get(soap);
15020  switch (c)
15021  {
15022  case SOAP_TT:
15023  if (n == 0)
15024  goto end;
15025  n--;
15026  break;
15027  case SOAP_LT:
15028  n++;
15029  break;
15030  case '/':
15031  if (n > 0)
15032  {
15033  c = soap_get0(soap);
15034  if (c == '>')
15035  n--;
15036  }
15037  break;
15038  default:
15039  if ((int)c == EOF)
15040  return soap->error = SOAP_EOF;
15041  }
15042  }
15043 end:
15044  soap_unget(soap, c);
15045  }
15046  return soap_element_end_in(soap, NULL);
15047 }
15048 
15049 /******************************************************************************/
15050 
15051 SOAP_FMAC1
15052 int
15053 SOAP_FMAC2
15054 soap_string_out(struct soap *soap, const char *s, int flag)
15055 {
15056  const char *t;
15057  soap_wchar c;
15058  soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
15059 #ifdef WITH_DOM
15060  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
15061  {
15062  soap->dom->text = soap_strdup(soap, s);
15063  if (!soap->dom->text)
15064  return soap->error = SOAP_EOM;
15065  return SOAP_OK;
15066  }
15067 #endif
15068  if (flag == 2 || (soap->mode & SOAP_C_UTFSTRING))
15069  mask = 0;
15070  t = s;
15071  while ((c = *t++))
15072  {
15073  switch (c)
15074  {
15075  case 0x09:
15076  if (flag)
15077  {
15078  if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
15079  return soap->error;
15080  s = t;
15081  }
15082  break;
15083  case 0x0A:
15084  if (flag)
15085  {
15086  if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
15087  return soap->error;
15088  s = t;
15089  }
15090  break;
15091  case '&':
15092  if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
15093  return soap->error;
15094  s = t;
15095  break;
15096  case '<':
15097  if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
15098  return soap->error;
15099  s = t;
15100  break;
15101  case '>':
15102  if (!flag)
15103  {
15104  if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
15105  return soap->error;
15106  s = t;
15107  }
15108  break;
15109  case '"':
15110  if (flag)
15111  {
15112  if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
15113  return soap->error;
15114  s = t;
15115  }
15116  break;
15117  case 0x7F:
15118  if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x7F;", 6))
15119  return soap->error;
15120  s = t;
15121  break;
15122  default:
15123 #ifndef WITH_LEANER
15124 #ifdef HAVE_MBTOWC
15125  if ((soap->mode & SOAP_C_MBSTRING))
15126  {
15127  wchar_t wc;
15128  int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
15129  if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80))
15130  {
15131  if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc))
15132  return soap->error;
15133  s = t += m - 1;
15134  continue;
15135  }
15136  }
15137 #endif
15138 #endif
15139 #ifndef WITH_NOSTRINGTOUTF8
15140  if ((c & mask) || !(c & 0xFFFFFFE0UL))
15141  {
15142  if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
15143  return soap->error;
15144  s = t;
15145  }
15146 #endif
15147  }
15148  }
15149  return soap_send_raw(soap, s, t - s - 1);
15150 }
15151 
15152 /******************************************************************************/
15153 
15154 SOAP_FMAC1
15155 char *
15156 SOAP_FMAC2
15157 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern)
15158 {
15159  char *s;
15160  char *t = NULL;
15161  size_t i;
15162  ULONG64 l = 0;
15163  int n = 0, f = 0, m = 0;
15164  soap_wchar c;
15165 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
15166  char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
15167 #else
15168  char buf[8];
15169 #endif
15170  if (maxlen < 0 && soap->maxlength > 0)
15171  maxlen = soap->maxlength;
15172  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
15173  if (flag <= 0 && soap->peeked && *soap->tag)
15174  {
15175 #ifndef WITH_LEAN
15176  struct soap_attribute *tp;
15177  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
15178  t = soap->tmpbuf;
15179  *t = '<';
15180  soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag);
15181  t += strlen(t);
15182  for (tp = soap->attributes; tp; tp = tp->next)
15183  {
15184  if (tp->visible)
15185  {
15186  size_t k = strlen(tp->name);
15187  if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf))
15188  break; /* too many or attribute values to large */
15189  *t++ = ' ';
15190  (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k);
15191  t += k;
15192  if (tp->value)
15193  {
15194  k = strlen(tp->value);
15195  if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf))
15196  break; /* too many or attribute values to large */
15197  *t++ = '=';
15198  *t++ = '"';
15199  (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k);
15200  t += k;
15201  *t++ = '"';
15202  }
15203  }
15204  }
15205  if (!soap->body)
15206  *t++ = '/';
15207  *t++ = '>';
15208  *t = '\0';
15209  t = soap->tmpbuf;
15210  m = (int)strlen(soap->tmpbuf);
15211 #endif
15212  if (soap->body)
15213  n = 1;
15214  f = 1;
15215  soap->peeked = 0;
15216  }
15217 #ifdef WITH_CDATA
15218  if (flag <= 0)
15219  {
15220  int state = 0;
15221 #ifdef WITH_FAST
15222  soap->labidx = 0; /* use look-aside buffer */
15223 #else
15224  if (soap_alloc_block(soap) == NULL)
15225  return NULL;
15226 #endif
15227  for (;;)
15228  {
15229 #ifdef WITH_FAST
15230  size_t k;
15231  if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
15232  return NULL;
15233  s = soap->labbuf + soap->labidx; /* space to populate */
15234  k = soap->lablen - soap->labidx; /* number of bytes available */
15235  soap->labidx = soap->lablen; /* claim this space */
15236 #else
15237  size_t k = SOAP_BLKLEN;
15238  s = (char*)soap_push_block(soap, NULL, k);
15239  if (!s)
15240  return NULL;
15241 #endif
15242  for (i = 0; i < k; i++)
15243  {
15244  if (m > 0)
15245  {
15246  *s++ = *t++; /* copy multibyte characters */
15247  m--;
15248  continue;
15249  }
15250  c = soap_getchar(soap);
15251  if ((int)c == EOF)
15252  goto end;
15253  if ((c >= 0x80 || c < SOAP_AP) && state != 1)
15254  {
15255  if ((c & 0x7FFFFFFF) >= 0x80)
15256  {
15257  soap_unget(soap, c);
15258  c = soap_getutf8(soap);
15259  }
15260  if ((c & 0x7FFFFFFF) >= 0x80 && (flag <= 0 || (soap->mode & SOAP_C_UTFSTRING)))
15261  {
15262  c &= 0x7FFFFFFF;
15263  t = buf;
15264  if (c < 0x0800)
15265  *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
15266  else
15267  {
15268 #ifdef WITH_REPLACE_ILLEGAL_UTF8
15269  if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
15270  c = SOAP_UNKNOWN_UNICODE_CHAR;
15271 #endif
15272  if (c < 0x010000)
15273  {
15274  *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
15275  }
15276  else
15277  {
15278  if (c < 0x200000)
15279  {
15280  *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
15281  }
15282  else
15283  {
15284  if (c < 0x04000000)
15285  {
15286  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
15287  }
15288  else
15289  {
15290  *t++ = (char)(0xFC | ((c >> 30) & 0x01));
15291  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
15292  }
15293  *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
15294  }
15295  *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
15296  }
15297  *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
15298  }
15299  *t++ = (char)(0x80 | (c & 0x3F));
15300  m = (int)(t - buf) - 1;
15301  t = buf;
15302  *s++ = *t++;
15303  continue;
15304  }
15305  }
15306  switch (state)
15307  {
15308  case 1:
15309  if (c == ']')
15310  state = 4;
15311  *s++ = (char)c;
15312  continue;
15313  case 2:
15314  if (c == '-')
15315  state = 6;
15316  *s++ = (char)c;
15317  continue;
15318  case 3:
15319  if (c == '?')
15320  state = 8;
15321  *s++ = (char)c;
15322  continue;
15323  /* CDATA */
15324  case 4:
15325  if (c == ']')
15326  state = 5;
15327  else
15328  state = 1;
15329  *s++ = (char)c;
15330  continue;
15331  case 5:
15332  if (c == '>')
15333  state = 0;
15334  else if (c != ']')
15335  state = 1;
15336  *s++ = (char)c;
15337  continue;
15338  /* comment */
15339  case 6:
15340  if (c == '-')
15341  state = 7;
15342  else
15343  state = 2;
15344  *s++ = (char)c;
15345  continue;
15346  case 7:
15347  if (c == '>')
15348  state = 0;
15349  else if (c != '-')
15350  state = 2;
15351  *s++ = (char)c;
15352  continue;
15353  /* PI */
15354  case 8:
15355  if (c == '>')
15356  state = 0;
15357  else if (c != '?')
15358  state = 3;
15359  *s++ = (char)c;
15360  continue;
15361  }
15362  switch (c)
15363  {
15364  case SOAP_TT:
15365  if (n == 0)
15366  goto end;
15367  n--;
15368  *s++ = '<';
15369  t = (char*)"/";
15370  m = 1;
15371  break;
15372  case SOAP_LT:
15373  if (flag == 3 || (f && n == 0))
15374  goto end;
15375  n++;
15376  *s++ = '<';
15377  break;
15378  case SOAP_GT:
15379  *s++ = '>';
15380  break;
15381  case SOAP_QT:
15382  *s++ = '"';
15383  break;
15384  case SOAP_AP:
15385  *s++ = '\'';
15386  break;
15387  case '/':
15388  if (n > 0)
15389  {
15390  c = soap_getchar(soap);
15391  if (c == '>')
15392  n--;
15393  soap_unget(soap, c);
15394  }
15395  *s++ = '/';
15396  break;
15397  case '<':
15398  c = soap_getchar(soap);
15399  if (c == '/')
15400  {
15401  if (n == 0)
15402  {
15403  c = SOAP_TT;
15404  goto end;
15405  }
15406  n--;
15407  }
15408  else if (c == '!')
15409  {
15410  c = soap_getchar(soap);
15411  if (c == '[')
15412  {
15413  do
15414  {
15415  c = soap_getchar(soap);
15416  } while ((int)c != EOF && c != '[');
15417  if ((int)c == EOF)
15418  goto end;
15419  t = (char*)"![CDATA[";
15420  m = 8;
15421  state = 1;
15422  }
15423  else if (c == '-')
15424  {
15425  c = soap_getchar(soap);
15426  if (c == '-')
15427  state = 2;
15428  t = (char*)"!-";
15429  m = 2;
15430  soap_unget(soap, c);
15431  }
15432  else
15433  {
15434  t = (char*)"!";
15435  m = 1;
15436  soap_unget(soap, c);
15437  }
15438  *s++ = '<';
15439  break;
15440  }
15441  else if (c == '?')
15442  {
15443  state = 3;
15444  }
15445  else if (flag == 3 || (f && n == 0))
15446  {
15447  soap_revget1(soap);
15448  c = '<';
15449  goto end;
15450  }
15451  else
15452  n++;
15453  soap_unget(soap, c);
15454  *s++ = '<';
15455  break;
15456  case '>':
15457  *s++ = '>';
15458  break;
15459  case '"':
15460  *s++ = '"';
15461  break;
15462  default:
15463 #ifndef WITH_LEANER
15464 #ifdef HAVE_WCTOMB
15465  if ((soap->mode & SOAP_C_MBSTRING))
15466  {
15467 #if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__)
15468  m = 0;
15469  wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
15470 #else
15471  m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
15472 #endif
15473  if (m >= 1 && m <= (int)MB_CUR_MAX)
15474  {
15475  t = buf;
15476  *s++ = *t++;
15477  m--;
15478  }
15479  else
15480  {
15481  *s++ = SOAP_UNKNOWN_CHAR;
15482  m = 0;
15483  }
15484  }
15485  else
15486 #endif
15487 #endif
15488  *s++ = (char)(c & 0xFF);
15489  }
15490  l++;
15491  if (maxlen >= 0 && l > (size_t)maxlen)
15492  {
15493  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
15494  soap->error = SOAP_LENGTH;
15495  return NULL;
15496  }
15497  }
15498  }
15499  }
15500 #endif
15501 #ifdef WITH_FAST
15502  soap->labidx = 0; /* use look-aside buffer */
15503 #else
15504  if (soap_alloc_block(soap) == NULL)
15505  return NULL;
15506 #endif
15507  for (;;)
15508  {
15509 #ifdef WITH_FAST
15510  size_t k;
15511  if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
15512  return NULL;
15513  s = soap->labbuf + soap->labidx; /* space to populate */
15514  k = soap->lablen - soap->labidx; /* number of bytes available */
15515  soap->labidx = soap->lablen; /* claim this space */
15516 #else
15517  size_t k = SOAP_BLKLEN;
15518  s = (char*)soap_push_block(soap, NULL, k);
15519  if (!s)
15520  return NULL;
15521 #endif
15522  for (i = 0; i < k; i++)
15523  {
15524  if (m > 0)
15525  {
15526  *s++ = *t++; /* copy multibyte characters */
15527  m--;
15528  continue;
15529  }
15530 #ifndef WITH_CDATA
15531  if (flag <= 0)
15532  c = soap_getchar(soap);
15533  else
15534 #endif
15535  {
15536  c = soap_getutf8(soap);
15537  if ((soap->mode & SOAP_C_UTFSTRING))
15538  {
15539  if (c >= 0x80 || (c < SOAP_AP && c >= -0x7FFFFF80))
15540  {
15541  c &= 0x7FFFFFFF;
15542  t = buf;
15543  if (c < 0x0800)
15544  {
15545  *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
15546  }
15547  else
15548  {
15549 #ifdef WITH_REPLACE_ILLEGAL_UTF8
15550  if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
15551  c = SOAP_UNKNOWN_UNICODE_CHAR;
15552 #endif
15553  if (c < 0x010000)
15554  {
15555  *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
15556  }
15557  else
15558  {
15559  if (c < 0x200000)
15560  {
15561  *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
15562  }
15563  else
15564  {
15565  if (c < 0x04000000)
15566  {
15567  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
15568  }
15569  else
15570  {
15571  *t++ = (char)(0xFC | ((c >> 30) & 0x01));
15572  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
15573  }
15574  *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
15575  }
15576  *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
15577  }
15578  *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
15579  }
15580  *t++ = (char)(0x80 | (c & 0x3F));
15581  m = (int)(t - buf) - 1;
15582  t = buf;
15583  *s++ = *t++;
15584  l++;
15585  if (maxlen >= 0 && l > (size_t)maxlen)
15586  {
15587  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
15588  soap->error = SOAP_LENGTH;
15589  return NULL;
15590  }
15591  continue;
15592  }
15593  }
15594  }
15595  switch (c)
15596  {
15597  case SOAP_TT:
15598  if (n == 0)
15599  goto end;
15600  n--;
15601  *s++ = '<';
15602  t = (char*)"/";
15603  m = 1;
15604  break;
15605  case SOAP_LT:
15606  if (flag == 3 || (f && n == 0))
15607  goto end;
15608  n++;
15609  *s++ = '<';
15610  break;
15611  case SOAP_GT:
15612  *s++ = '>';
15613  break;
15614  case SOAP_QT:
15615  *s++ = '"';
15616  break;
15617  case SOAP_AP:
15618  *s++ = '\'';
15619  break;
15620  case '/':
15621  if (n > 0)
15622  {
15623  if (flag > 0)
15624  {
15625  c = soap_get(soap);
15626  if (c == SOAP_GT)
15627  n--;
15628  }
15629  else
15630  {
15631  c = soap_getchar(soap);
15632  if (c == '>')
15633  n--;
15634  }
15635  soap_unget(soap, c);
15636  }
15637  *s++ = '/';
15638  break;
15639  case (soap_wchar)('<' | 0x80000000):
15640  if (flag > 0)
15641  {
15642  *s++ = '<';
15643  }
15644  else
15645  {
15646  *s++ = '&';
15647  t = (char*)"lt;";
15648  m = 3;
15649  }
15650  break;
15651  case (soap_wchar)('>' | 0x80000000):
15652  if (flag > 0)
15653  {
15654  *s++ = '>';
15655  }
15656  else
15657  {
15658  *s++ = '&';
15659  t = (char*)"gt;";
15660  m = 3;
15661  }
15662  break;
15663  case (soap_wchar)('&' | 0x80000000):
15664  if (flag > 0)
15665  {
15666  *s++ = '&';
15667  }
15668  else
15669  {
15670  *s++ = '&';
15671  t = (char*)"amp;";
15672  m = 4;
15673  }
15674  break;
15675  case (soap_wchar)('"' | 0x80000000):
15676  if (flag > 0)
15677  {
15678  *s++ = '"';
15679  }
15680  else
15681  {
15682  *s++ = '&';
15683  t = (char*)"quot;";
15684  m = 5;
15685  }
15686  break;
15687  case (soap_wchar)('\'' | 0x80000000):
15688  if (flag > 0)
15689  {
15690  *s++ = '\'';
15691  }
15692  else
15693  {
15694  *s++ = '&';
15695  t = (char*)"apos;";
15696  m = 5;
15697  }
15698  break;
15699  default:
15700  if ((int)c == EOF)
15701  goto end;
15702 #ifndef WITH_CDATA
15703  if (c == '<')
15704  {
15705  c = soap_getchar(soap);
15706  soap_unget(soap, c);
15707  if (c == '/')
15708  {
15709  c = SOAP_TT;
15710  if (n == 0)
15711  goto end;
15712  n--;
15713  }
15714  else
15715  {
15716  n++;
15717  }
15718  *s++ = '<';
15719  }
15720  else
15721 #endif
15722 #ifndef WITH_LEANER
15723 #ifdef HAVE_WCTOMB
15724  if ((soap->mode & SOAP_C_MBSTRING))
15725  {
15726 #if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__BORLANDC__)
15727  m = 0;
15728  wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
15729 #else
15730  m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
15731 #endif
15732  if (m >= 1 && m <= (int)MB_CUR_MAX)
15733  {
15734  t = buf;
15735  *s++ = *t++;
15736  m--;
15737  }
15738  else
15739  {
15740  *s++ = SOAP_UNKNOWN_CHAR;
15741  m = 0;
15742  }
15743  }
15744  else
15745 #endif
15746 #endif
15747  *s++ = (char)(c & 0xFF);
15748  }
15749  l++;
15750  if (maxlen >= 0 && l > (size_t)maxlen)
15751  {
15752  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
15753  soap->error = SOAP_LENGTH;
15754  return NULL;
15755  }
15756  }
15757  }
15758 end:
15759  soap_unget(soap, c);
15760  *s = '\0';
15761 #ifdef WITH_FAST
15762  t = soap_strdup(soap, soap->labbuf);
15763  if (!t)
15764  return NULL;
15765 #else
15766  soap_size_block(soap, NULL, i + 1);
15767  t = soap_save_block(soap, NULL, NULL, 0);
15768 #endif
15769  if (minlen > 0 && l < (size_t)minlen)
15770  {
15771  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long)l, minlen));
15772  soap->error = SOAP_LENGTH;
15773  return NULL;
15774  }
15775 #ifdef WITH_DOM
15776  if ((soap->mode & SOAP_XML_DOM) && soap->dom && *t)
15777  {
15778  if (flag > 0)
15779  soap->dom->text = t;
15780  else
15781  soap->dom->code = t;
15782  }
15783 #endif
15784  if (flag == 2)
15785  {
15786  if (soap_s2QName(soap, t, &t, minlen, maxlen, pattern))
15787  return NULL;
15788  }
15789  else if (flag >= 4 && t)
15790  {
15791  t = soap_collapse(soap, t, flag, 1);
15792  }
15793 #ifndef WITH_LEANER
15794  else if (pattern && soap->fsvalidate)
15795  {
15796  soap->error = soap->fsvalidate(soap, pattern, t);
15797  if (soap->error)
15798  return NULL;
15799  }
15800 #endif
15801  return t;
15802 }
15803 
15804 /******************************************************************************/
15805 
15806 #ifndef WITH_LEANER
15807 SOAP_FMAC1
15808 int
15809 SOAP_FMAC2
15810 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
15811 {
15812  const char *t;
15813  char tmp;
15814  soap_wchar c;
15815 #ifdef WITH_DOM
15816  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
15817  {
15818  soap->dom->text = soap_wchar2s(soap, s);
15819  return SOAP_OK;
15820  }
15821 #endif
15822  while ((c = *s++))
15823  {
15824  switch (c)
15825  {
15826  case 0x09:
15827  if (flag)
15828  t = "&#x9;";
15829  else
15830  t = "\t";
15831  break;
15832  case 0x0A:
15833  if (flag)
15834  t = "&#xA;";
15835  else
15836  t = "\n";
15837  break;
15838  case '&':
15839  t = "&amp;";
15840  break;
15841  case '<':
15842  t = "&lt;";
15843  break;
15844  case '>':
15845  if (flag)
15846  t = ">";
15847  else
15848  t = "&gt;";
15849  break;
15850  case '"':
15851  if (flag)
15852  t = "&quot;";
15853  else
15854  t = "\"";
15855  break;
15856  default:
15857  if (c >= 0x20 && c < 0x80)
15858  {
15859  tmp = (char)c;
15860  if (soap_send_raw(soap, &tmp, 1))
15861  return soap->error;
15862  }
15863  else
15864  {
15865  /* check for UTF16 encoding when wchar_t is too small to hold UCS */
15866  if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
15867  {
15868  soap_wchar d = *s;
15869  if ((d & 0xFC00) == 0xDC00)
15870  {
15871  c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
15872  s++;
15873  }
15874 #ifdef WITH_REPLACE_ILLEGAL_UTF8
15875  else
15876  {
15877  c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */
15878  }
15879 #endif
15880  }
15881  if (soap_pututf8(soap, (unsigned long)c))
15882  return soap->error;
15883  }
15884  continue;
15885  }
15886  if (soap_send(soap, t))
15887  return soap->error;
15888  }
15889  return SOAP_OK;
15890 }
15891 #endif
15892 
15893 /******************************************************************************/
15894 
15895 #ifndef WITH_LEANER
15896 SOAP_FMAC1
15897 wchar_t *
15898 SOAP_FMAC2
15899 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern)
15900 {
15901  wchar_t *s;
15902  int i, n = 0, f = 0;
15903  ULONG64 l = 0;
15904  soap_wchar c;
15905  char *t = NULL;
15906  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
15907  if (maxlen < 0 && soap->maxlength > 0)
15908  maxlen = soap->maxlength;
15909  if (flag <= 0 && soap->peeked && *soap->tag)
15910  {
15911 #ifndef WITH_LEAN
15912  struct soap_attribute *tp;
15913  t = soap->tmpbuf;
15914  *t = '<';
15915  soap_strcpy(t + 1, sizeof(soap->tmpbuf) - 1, soap->tag);
15916  t += strlen(t);
15917  for (tp = soap->attributes; tp; tp = tp->next)
15918  {
15919  if (tp->visible)
15920  {
15921  size_t k = strlen(tp->name);
15922  if (t + k + 1 >= soap->tmpbuf + sizeof(soap->tmpbuf))
15923  break;
15924  *t++ = ' ';
15925  (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->name, k);
15926  t += k;
15927  if (tp->value)
15928  {
15929  k = strlen(tp->value);
15930  if (t + k + 3 >= soap->tmpbuf + sizeof(soap->tmpbuf))
15931  break;
15932  *t++ = '=';
15933  *t++ = '"';
15934  (void)soap_strncpy(t, sizeof(soap->tmpbuf) - (t - soap->tmpbuf), tp->value, k);
15935  t += k;
15936  *t++ = '"';
15937  }
15938  }
15939  }
15940  if (!soap->body)
15941  *t++ = '/';
15942  *t++ = '>';
15943  *t = '\0';
15944  t = soap->tmpbuf;
15945 #endif
15946  if (soap->body)
15947  n = 1;
15948  f = 1;
15949  soap->peeked = 0;
15950  }
15951  if (soap_alloc_block(soap) == NULL)
15952  return NULL;
15953  for (;;)
15954  {
15955  s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN);
15956  if (!s)
15957  return NULL;
15958  for (i = 0; i < SOAP_BLKLEN; i++)
15959  {
15960  if (t)
15961  {
15962  *s++ = (wchar_t)*t++;
15963  if (!*t)
15964  t = NULL;
15965  continue;
15966  }
15967  c = soap_getutf8(soap);
15968  switch (c)
15969  {
15970  case SOAP_TT:
15971  if (n == 0)
15972  goto end;
15973  n--;
15974  *s++ = L'<';
15975  soap_unget(soap, '/');
15976  break;
15977  case SOAP_LT:
15978  if (flag == 3 || (f && n == 0))
15979  goto end;
15980  n++;
15981  *s++ = L'<';
15982  break;
15983  case SOAP_GT:
15984  *s++ = L'>';
15985  break;
15986  case SOAP_QT:
15987  *s++ = L'"';
15988  break;
15989  case SOAP_AP:
15990  *s++ = L'\'';
15991  break;
15992  case '/':
15993  if (n > 0)
15994  {
15995  c = soap_getutf8(soap);
15996  if (c == SOAP_GT)
15997  n--;
15998  soap_unget(soap, c);
15999  }
16000  *s++ = L'/';
16001  break;
16002  case '<':
16003  if (flag > 0)
16004  {
16005  *s++ = L'<';
16006  }
16007  else
16008  {
16009  *s++ = L'&';
16010  t = (char*)"lt;";
16011  }
16012  break;
16013  case '>':
16014  if (flag > 0)
16015  {
16016  *s++ = L'>';
16017  }
16018  else
16019  {
16020  *s++ = (wchar_t)'&';
16021  t = (char*)"gt;";
16022  }
16023  break;
16024  case '"':
16025  if (flag > 0)
16026  {
16027  *s++ = L'"';
16028  }
16029  else
16030  {
16031  *s++ = L'&';
16032  t = (char*)"quot;";
16033  }
16034  break;
16035  default:
16036  if ((int)c == EOF)
16037  goto end;
16038  /* use UTF16 encoding when wchar_t is too small to hold UCS */
16039  if (sizeof(wchar_t) < 4 && c > 0xFFFF)
16040  {
16041  soap_wchar c1, c2;
16042  c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
16043  c2 = 0xDC00 + (c & 0x3FF);
16044  c = c1;
16045  soap_unget(soap, c2);
16046  }
16047  *s++ = (wchar_t)(c & 0x7FFFFFFF);
16048  }
16049  l++;
16050  if (maxlen >= 0 && l > (size_t)maxlen)
16051  {
16052  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
16053  soap->error = SOAP_LENGTH;
16054  return NULL;
16055  }
16056  }
16057  }
16058 end:
16059  soap_unget(soap, c);
16060  *s = L'\0';
16061  soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
16062  if (minlen > 0 && l < (size_t)minlen)
16063  {
16064  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "String too short: %lu chars, minlen=%ld\n", (unsigned long)l, minlen));
16065  soap->error = SOAP_LENGTH;
16066  return NULL;
16067  }
16068  s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
16069 #ifndef WITH_LEAN
16070  if (flag >= 4 && s)
16071  s = soap_wcollapse(soap, s, flag, 1);
16072 #endif
16073 #ifndef WITH_LEANER
16074  if (pattern && soap->fwvalidate)
16075  {
16076  soap->error = soap->fwvalidate(soap, pattern, s);
16077  if (soap->error)
16078  return NULL;
16079  }
16080 #endif
16081 #ifdef WITH_DOM
16082  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
16083  soap->dom->text = soap_wchar2s(soap, s);
16084 #endif
16085  return s;
16086 }
16087 #endif
16088 
16089 /******************************************************************************/
16090 
16091 SOAP_FMAC1
16092 const char*
16093 SOAP_FMAC2
16094 soap_int2s(struct soap *soap, int n)
16095 {
16096  return soap_long2s(soap, (long)n);
16097 }
16098 
16099 /******************************************************************************/
16100 
16101 SOAP_FMAC1
16102 int
16103 SOAP_FMAC2
16104 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
16105 {
16106  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16107  || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
16108  return soap->error;
16109  return soap_element_end_out(soap, tag);
16110 }
16111 
16112 /******************************************************************************/
16113 
16114 SOAP_FMAC1
16115 int
16116 SOAP_FMAC2
16117 soap_s2int(struct soap *soap, const char *s, int *p)
16118 {
16119  if (s)
16120  {
16121  long n;
16122  char *r;
16123  if (!*s)
16124  return soap->error = SOAP_EMPTY;
16125 #ifndef WITH_NOIO
16126 #ifndef WITH_LEAN
16128 #endif
16129 #endif
16130  n = soap_strtol(s, &r, 10);
16131  if (s == r || *r
16132 #ifndef WITH_LEAN
16133  || n != (int)n
16134 #endif
16135 #ifndef WITH_NOIO
16136 #ifndef WITH_LEAN
16137  || soap_errno == SOAP_ERANGE
16138 #endif
16139 #endif
16140  )
16141  soap->error = SOAP_TYPE;
16142  *p = (int)n;
16143  }
16144  return soap->error;
16145 }
16146 
16147 /******************************************************************************/
16148 
16149 SOAP_FMAC1
16150 int *
16151 SOAP_FMAC2
16152 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
16153 {
16154  if (soap_element_begin_in(soap, tag, 0, NULL))
16155  return NULL;
16156 #ifndef WITH_LEAN
16157  if (*soap->type
16159  && soap_match_tag(soap, soap->type, ":int")
16160  && soap_match_tag(soap, soap->type, ":short")
16161  && soap_match_tag(soap, soap->type, ":byte"))
16162  {
16163  soap->error = SOAP_TYPE;
16164  soap_revert(soap);
16165  return NULL;
16166  }
16167 #else
16168  (void)type;
16169 #endif
16170  p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), NULL, NULL, NULL, NULL);
16171  if (!p)
16172  return NULL;
16173  if (*soap->href != '#')
16174  {
16175  int err = soap_s2int(soap, soap_value(soap), p);
16176  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16177  return NULL;
16178  }
16179  else
16180  {
16181  p = (int*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(int), 0, NULL, NULL);
16182  if (soap->body && soap_element_end_in(soap, tag))
16183  return NULL;
16184  }
16185  return p;
16186 }
16187 
16188 /******************************************************************************/
16189 
16190 SOAP_FMAC1
16191 const char*
16192 SOAP_FMAC2
16193 soap_long2s(struct soap *soap, long n)
16194 {
16195  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%ld", n);
16196  return soap->tmpbuf;
16197 }
16198 
16199 /******************************************************************************/
16200 
16201 SOAP_FMAC1
16202 int
16203 SOAP_FMAC2
16204 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
16205 {
16206  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16207  || soap_string_out(soap, soap_long2s(soap, *p), 0))
16208  return soap->error;
16209  return soap_element_end_out(soap, tag);
16210 }
16211 
16212 /******************************************************************************/
16213 
16214 SOAP_FMAC1
16215 int
16216 SOAP_FMAC2
16217 soap_s2long(struct soap *soap, const char *s, long *p)
16218 {
16219  if (s)
16220  {
16221  char *r;
16222  if (!*s)
16223  return soap->error = SOAP_EMPTY;
16224 #ifndef WITH_NOIO
16225 #ifndef WITH_LEAN
16227 #endif
16228 #endif
16229  *p = soap_strtol(s, &r, 10);
16230  if (s == r || *r
16231 #ifndef WITH_NOIO
16232 #ifndef WITH_LEAN
16233  || soap_errno == SOAP_ERANGE
16234 #endif
16235 #endif
16236  )
16237  soap->error = SOAP_TYPE;
16238  }
16239  return soap->error;
16240 }
16241 
16242 /******************************************************************************/
16243 
16244 SOAP_FMAC1
16245 long *
16246 SOAP_FMAC2
16247 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
16248 {
16249  if (soap_element_begin_in(soap, tag, 0, NULL))
16250  return NULL;
16251 #ifndef WITH_LEAN
16252  if (*soap->type
16254  && soap_match_tag(soap, soap->type, ":int")
16255  && soap_match_tag(soap, soap->type, ":short")
16256  && soap_match_tag(soap, soap->type, ":byte"))
16257  {
16258  soap->error = SOAP_TYPE;
16259  soap_revert(soap);
16260  return NULL;
16261  }
16262 #else
16263  (void)type;
16264 #endif
16265  p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), NULL, NULL, NULL, NULL);
16266  if (!p)
16267  return NULL;
16268  if (*soap->href != '#')
16269  {
16270  int err = soap_s2long(soap, soap_value(soap), p);
16271  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16272  return NULL;
16273  }
16274  else
16275  {
16276  p = (long*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(long), 0, NULL, NULL);
16277  if (soap->body && soap_element_end_in(soap, tag))
16278  return NULL;
16279  }
16280  return p;
16281 }
16282 
16283 /******************************************************************************/
16284 
16285 SOAP_FMAC1
16286 const char*
16287 SOAP_FMAC2
16289 {
16290  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_LONG_FORMAT, n);
16291  return soap->tmpbuf;
16292 }
16293 
16294 /******************************************************************************/
16295 
16296 SOAP_FMAC1
16297 int
16298 SOAP_FMAC2
16299 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
16300 {
16301  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16302  || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
16303  return soap->error;
16304  return soap_element_end_out(soap, tag);
16305 }
16306 
16307 /******************************************************************************/
16308 
16309 SOAP_FMAC1
16310 int
16311 SOAP_FMAC2
16312 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
16313 {
16314  if (s)
16315  {
16316  char *r;
16317  if (!*s)
16318  return soap->error = SOAP_EMPTY;
16319 #ifndef WITH_NOIO
16320 #ifndef WITH_LEAN
16322 #endif
16323 #endif
16324  *p = soap_strtoll(s, &r, 10);
16325  if (s == r || *r
16326 #ifndef WITH_NOIO
16327 #ifndef WITH_LEAN
16328  || soap_errno == SOAP_ERANGE
16329 #endif
16330 #endif
16331  )
16332  soap->error = SOAP_TYPE;
16333  }
16334  return soap->error;
16335 }
16336 
16337 /******************************************************************************/
16338 
16339 SOAP_FMAC1
16340 LONG64 *
16341 SOAP_FMAC2
16342 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
16343 {
16344  if (soap_element_begin_in(soap, tag, 0, NULL))
16345  return NULL;
16346 #ifndef WITH_LEAN
16347  if (*soap->type
16349  && soap_match_tag(soap, soap->type, ":integer")
16350  && soap_match_tag(soap, soap->type, ":positiveInteger")
16351  && soap_match_tag(soap, soap->type, ":negativeInteger")
16352  && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
16353  && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
16354  && soap_match_tag(soap, soap->type, ":long")
16355  && soap_match_tag(soap, soap->type, ":int")
16356  && soap_match_tag(soap, soap->type, ":short")
16357  && soap_match_tag(soap, soap->type, ":byte"))
16358  {
16359  soap->error = SOAP_TYPE;
16360  soap_revert(soap);
16361  return NULL;
16362  }
16363 #else
16364  (void)type;
16365 #endif
16366  p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), NULL, NULL, NULL, NULL);
16367  if (!p)
16368  return NULL;
16369  if (*soap->href != '#')
16370  {
16371  int err = soap_s2LONG64(soap, soap_value(soap), p);
16372  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16373  return NULL;
16374  }
16375  else
16376  {
16377  p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(LONG64), 0, NULL, NULL);
16378  if (soap->body && soap_element_end_in(soap, tag))
16379  return NULL;
16380  }
16381  return p;
16382 }
16383 
16384 /******************************************************************************/
16385 
16386 SOAP_FMAC1
16387 const char*
16388 SOAP_FMAC2
16389 soap_byte2s(struct soap *soap, char n)
16390 {
16391  return soap_long2s(soap, (long)n);
16392 }
16393 
16394 /******************************************************************************/
16395 
16396 SOAP_FMAC1
16397 int
16398 SOAP_FMAC2
16399 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
16400 {
16401  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16402  || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
16403  return soap->error;
16404  return soap_element_end_out(soap, tag);
16405 }
16406 
16407 /******************************************************************************/
16408 
16409 SOAP_FMAC1
16410 int
16411 SOAP_FMAC2
16412 soap_s2byte(struct soap *soap, const char *s, char *p)
16413 {
16414  if (s)
16415  {
16416  long n;
16417  char *r;
16418  if (!*s)
16419  return soap->error = SOAP_EMPTY;
16420  n = soap_strtol(s, &r, 10);
16421  if (s == r || *r || n < -128 || n > 127)
16422  soap->error = SOAP_TYPE;
16423  *p = (char)n;
16424  }
16425  return soap->error;
16426 }
16427 
16428 /******************************************************************************/
16429 
16430 SOAP_FMAC1
16431 char *
16432 SOAP_FMAC2
16433 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
16434 {
16435  if (soap_element_begin_in(soap, tag, 0, NULL))
16436  return NULL;
16437 #ifndef WITH_LEAN
16438  if (*soap->type
16440  && soap_match_tag(soap, soap->type, ":byte"))
16441  {
16442  soap->error = SOAP_TYPE;
16443  soap_revert(soap);
16444  return NULL;
16445  }
16446 #else
16447  (void)type;
16448 #endif
16449  p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), NULL, NULL, NULL, NULL);
16450  if (!p)
16451  return NULL;
16452  if (*soap->href != '#')
16453  {
16454  int err = soap_s2byte(soap, soap_value(soap), p);
16455  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16456  return NULL;
16457  }
16458  else
16459  {
16460  p = (char*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(char), 0, NULL, NULL);
16461  if (soap->body && soap_element_end_in(soap, tag))
16462  return NULL;
16463  }
16464  return p;
16465 }
16466 
16467 /******************************************************************************/
16468 
16469 SOAP_FMAC1
16470 const char*
16471 SOAP_FMAC2
16472 soap_short2s(struct soap *soap, short n)
16473 {
16474  return soap_long2s(soap, (long)n);
16475 }
16476 
16477 /******************************************************************************/
16478 
16479 SOAP_FMAC1
16480 int
16481 SOAP_FMAC2
16482 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
16483 {
16484  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16485  || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
16486  return soap->error;
16487  return soap_element_end_out(soap, tag);
16488 }
16489 
16490 /******************************************************************************/
16491 
16492 SOAP_FMAC1
16493 int
16494 SOAP_FMAC2
16495 soap_s2short(struct soap *soap, const char *s, short *p)
16496 {
16497  if (s)
16498  {
16499  long n;
16500  char *r;
16501  if (!*s)
16502  return soap->error = SOAP_EMPTY;
16503  n = soap_strtol(s, &r, 10);
16504  if (s == r || *r || n < -32768 || n > 32767)
16505  soap->error = SOAP_TYPE;
16506  *p = (short)n;
16507  }
16508  return soap->error;
16509 }
16510 
16511 /******************************************************************************/
16512 
16513 SOAP_FMAC1
16514 short *
16515 SOAP_FMAC2
16516 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
16517 {
16518  if (soap_element_begin_in(soap, tag, 0, NULL))
16519  return NULL;
16520 #ifndef WITH_LEAN
16521  if (*soap->type
16523  && soap_match_tag(soap, soap->type, ":short")
16524  && soap_match_tag(soap, soap->type, ":byte"))
16525  {
16526  soap->error = SOAP_TYPE;
16527  soap_revert(soap);
16528  return NULL;
16529  }
16530 #else
16531  (void)type;
16532 #endif
16533  p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), NULL, NULL, NULL, NULL);
16534  if (!p)
16535  return NULL;
16536  if (*soap->href != '#')
16537  {
16538  int err = soap_s2short(soap, soap_value(soap), p);
16539  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16540  return NULL;
16541  }
16542  else
16543  {
16544  p = (short*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(short), 0, NULL, NULL);
16545  if (soap->body && soap_element_end_in(soap, tag))
16546  return NULL;
16547  }
16548  return p;
16549 }
16550 
16551 /******************************************************************************/
16552 
16553 SOAP_FMAC1
16554 const char*
16555 SOAP_FMAC2
16556 soap_float2s(struct soap *soap, float n)
16557 {
16558 #if defined(WITH_C_LOCALE)
16559 # if !defined(WIN32)
16560  SOAP_LOCALE_T locale;
16561 # endif
16562 #else
16563  char *s;
16564 #endif
16565  if (soap_isnan((double)n))
16566  return "NaN";
16567  if (soap_ispinff(n))
16568  return "INF";
16569  if (soap_isninff(n))
16570  return "-INF";
16571 #if defined(WITH_C_LOCALE)
16572 # ifdef WIN32
16573  _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, SOAP_LOCALE(soap), n);
16574 # else
16575  locale = uselocale(SOAP_LOCALE(soap));
16576  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), soap->float_format, n);
16577  uselocale(locale);
16578 # endif
16579 #else
16580  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), soap->float_format, n);
16581  s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
16582  if (s)
16583  *s = '.';
16584 #endif
16585  return soap->tmpbuf;
16586 }
16587 
16588 /******************************************************************************/
16589 
16590 SOAP_FMAC1
16591 int
16592 SOAP_FMAC2
16593 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
16594 {
16595  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16596  || soap_string_out(soap, soap_float2s(soap, *p), 0))
16597  return soap->error;
16598  return soap_element_end_out(soap, tag);
16599 }
16600 
16601 /******************************************************************************/
16602 
16603 SOAP_FMAC1
16604 int
16605 SOAP_FMAC2
16606 soap_s2float(struct soap *soap, const char *s, float *p)
16607 {
16608  if (s)
16609  {
16610  if (!*s)
16611  return soap->error = SOAP_EMPTY;
16612  if (!soap_tag_cmp(s, "INF"))
16613  {
16614  *p = FLT_PINFTY;
16615  }
16616  else if (!soap_tag_cmp(s, "+INF"))
16617  {
16618  *p = FLT_PINFTY;
16619  }
16620  else if (!soap_tag_cmp(s, "-INF"))
16621  {
16622  *p = FLT_NINFTY;
16623  }
16624  else if (!soap_tag_cmp(s, "NaN"))
16625  {
16626  *p = FLT_NAN;
16627  }
16628  else
16629  {
16630 /* On some systems strtof requires -std=c99 or does not even link: so we try strtod first */
16631 #if defined(WITH_C_LOCALE)
16632 # if defined(HAVE_STRTOD_L)
16633  char *r;
16634 # ifdef WIN32
16635  *p = (float)_strtod_l(s, &r, SOAP_LOCALE(soap));
16636 # else
16637  *p = (float)strtod_l(s, &r, SOAP_LOCALE(soap));
16638 # endif
16639  if (*r)
16640  soap->error = SOAP_TYPE;
16641 # elif defined(HAVE_STRTOF_L)
16642  char *r;
16643  *p = strtof_l((char*)s, &r, SOAP_LOCALE(soap));
16644  if (*r)
16645  soap->error = SOAP_TYPE;
16646 # elif defined(HAVE_SSCANF_L)
16647  double n;
16648  if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", &n) != 1)
16649  soap->error = SOAP_TYPE;
16650  *p = (float)n;
16651 # elif defined(HAVE_STRTOD)
16652  char *r;
16653  SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
16654  *p = (float)strtod((char*)s, &r);
16655  uselocale(locale);
16656  if (*r)
16657  soap->error = SOAP_TYPE;
16658 # elif defined(HAVE_STRTOF)
16659  char *r;
16660  SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
16661  *p = strtof((char*)s, &r);
16662  uselocale(locale);
16663  if (*r)
16664  soap->error = SOAP_TYPE;
16665 # elif defined(HAVE_SSCANF)
16666  double n;
16667  SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
16668  if (sscanf(s, "%lf", &n) != 1)
16669  soap->error = SOAP_TYPE;
16670  uselocale(locale);
16671  *p = (float)n;
16672 # else
16673  soap->error = SOAP_TYPE;
16674 # endif
16675 #elif defined(HAVE_STRTOD)
16676  char *r;
16677  *p = (float)strtod(s, &r);
16678  if (*r)
16679  soap->error = SOAP_TYPE;
16680 #elif defined(HAVE_STRTOF)
16681  char *r;
16682  *p = strtof((char*)s, &r);
16683  if (*r)
16684  soap->error = SOAP_TYPE;
16685 #elif defined(HAVE_SSCANF)
16686  double n;
16687  if (sscanf(s, "%lf", &n) != 1)
16688  soap->error = SOAP_TYPE;
16689  *p = (float)n;
16690 #else
16691  soap->error = SOAP_TYPE;
16692 #endif
16693  }
16694  }
16695  return soap->error;
16696 }
16697 
16698 /******************************************************************************/
16699 
16700 #ifndef WITH_LEAN
16701 static int soap_isnumeric(struct soap *soap, const char *type)
16702 {
16703  if (soap_match_tag(soap, soap->type, type)
16704  && soap_match_tag(soap, soap->type, ":float")
16705  && soap_match_tag(soap, soap->type, ":double")
16706  && soap_match_tag(soap, soap->type, ":decimal")
16707  && soap_match_tag(soap, soap->type, ":integer")
16708  && soap_match_tag(soap, soap->type, ":positiveInteger")
16709  && soap_match_tag(soap, soap->type, ":negativeInteger")
16710  && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
16711  && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
16712  && soap_match_tag(soap, soap->type, ":long")
16713  && soap_match_tag(soap, soap->type, ":int")
16714  && soap_match_tag(soap, soap->type, ":short")
16715  && soap_match_tag(soap, soap->type, ":byte")
16716  && soap_match_tag(soap, soap->type, ":unsignedLong")
16717  && soap_match_tag(soap, soap->type, ":unsignedInt")
16718  && soap_match_tag(soap, soap->type, ":unsignedShort")
16719  && soap_match_tag(soap, soap->type, ":unsignedByte"))
16720  {
16721  soap->error = SOAP_TYPE;
16722  soap_revert(soap);
16723  return SOAP_ERR;
16724  }
16725  return SOAP_OK;
16726 }
16727 #endif
16728 
16729 /******************************************************************************/
16730 
16731 SOAP_FMAC1
16732 float *
16733 SOAP_FMAC2
16734 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
16735 {
16736  if (soap_element_begin_in(soap, tag, 0, NULL))
16737  return NULL;
16738 #ifndef WITH_LEAN
16739  if (*soap->type != '\0' && soap_isnumeric(soap, type))
16740  return NULL;
16741 #else
16742  (void)type;
16743 #endif
16744  p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), NULL, NULL, NULL, NULL);
16745  if (!p)
16746  return NULL;
16747  if (*soap->href != '#')
16748  {
16749  int err = soap_s2float(soap, soap_value(soap), p);
16750  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16751  return NULL;
16752  }
16753  else
16754  {
16755  p = (float*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(float), 0, NULL, NULL);
16756  if (soap->body && soap_element_end_in(soap, tag))
16757  return NULL;
16758  }
16759  return p;
16760 }
16761 
16762 /******************************************************************************/
16763 
16764 SOAP_FMAC1
16765 const char*
16766 SOAP_FMAC2
16767 soap_double2s(struct soap *soap, double n)
16768 {
16769 #if defined(WITH_C_LOCALE)
16770 # if !defined(WIN32)
16771  SOAP_LOCALE_T locale;
16772 # endif
16773 #else
16774  char *s;
16775 #endif
16776  if (soap_isnan(n))
16777  return "NaN";
16778  if (soap_ispinfd(n))
16779  return "INF";
16780  if (soap_isninfd(n))
16781  return "-INF";
16782 #if defined(WITH_C_LOCALE)
16783 # ifdef WIN32
16784  _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, SOAP_LOCALE(soap), n);
16785 # else
16786  locale = uselocale(SOAP_LOCALE(soap));
16787  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 40), soap->double_format, n);
16788  uselocale(locale);
16789 # endif
16790 #else
16791  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 40), soap->double_format, n);
16792  s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
16793  if (s)
16794  *s = '.';
16795 #endif
16796  return soap->tmpbuf;
16797 }
16798 
16799 /******************************************************************************/
16800 
16801 SOAP_FMAC1
16802 int
16803 SOAP_FMAC2
16804 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
16805 {
16806  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16807  || soap_string_out(soap, soap_double2s(soap, *p), 0))
16808  return soap->error;
16809  return soap_element_end_out(soap, tag);
16810 }
16811 
16812 /******************************************************************************/
16813 
16814 SOAP_FMAC1
16815 int
16816 SOAP_FMAC2
16817 soap_s2double(struct soap *soap, const char *s, double *p)
16818 {
16819  if (s)
16820  {
16821  if (!*s)
16822  return soap->error = SOAP_EMPTY;
16823  if (!soap_tag_cmp(s, "INF"))
16824  {
16825  *p = DBL_PINFTY;
16826  }
16827  else if (!soap_tag_cmp(s, "+INF"))
16828  {
16829  *p = DBL_PINFTY;
16830  }
16831  else if (!soap_tag_cmp(s, "-INF"))
16832  {
16833  *p = DBL_NINFTY;
16834  }
16835  else if (!soap_tag_cmp(s, "NaN"))
16836  {
16837  *p = DBL_NAN;
16838  }
16839  else
16840  {
16841 #if defined(WITH_C_LOCALE)
16842 # if defined(HAVE_STRTOD_L)
16843  char *r;
16844 # ifdef WIN32
16845  *p = _strtod_l(s, &r, SOAP_LOCALE(soap));
16846 # else
16847  *p = strtod_l(s, &r, SOAP_LOCALE(soap));
16848 # endif
16849  if (*r)
16850  soap->error = SOAP_TYPE;
16851 # elif defined(HAVE_STRTOD)
16852  char *r;
16853  SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
16854  *p = strtod(s, &r);
16855  uselocale(locale);
16856  if (*r)
16857  soap->error = SOAP_TYPE;
16858 # elif defined(HAVE_SSCANF_L)
16859  SOAP_LOCALE_T locale = uselocale(SOAP_LOCALE(soap));
16860  if (sscanf_l(s, SOAP_LOCALE(soap), "%lf", p) != 1)
16861  soap->error = SOAP_TYPE;
16862  uselocale(locale);
16863 # else
16864  soap->error = SOAP_TYPE;
16865 # endif
16866 #elif defined(HAVE_STRTOD)
16867  char *r;
16868  *p = strtod(s, &r);
16869  if (*r)
16870  soap->error = SOAP_TYPE;
16871 #elif defined(HAVE_SSCANF)
16872  if (sscanf(s, "%lf", p) != 1)
16873  soap->error = SOAP_TYPE;
16874 #else
16875  soap->error = SOAP_TYPE;
16876 #endif
16877  }
16878  }
16879  return soap->error;
16880 }
16881 
16882 /******************************************************************************/
16883 
16884 SOAP_FMAC1
16885 double *
16886 SOAP_FMAC2
16887 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
16888 {
16889  if (soap_element_begin_in(soap, tag, 0, NULL))
16890  return NULL;
16891 #ifndef WITH_LEAN
16892  if (*soap->type != '\0' && soap_isnumeric(soap, type))
16893  return NULL;
16894 #else
16895  (void)type;
16896 #endif
16897  p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), NULL, NULL, NULL, NULL);
16898  if (!p)
16899  return NULL;
16900  if (*soap->href != '#')
16901  {
16902  int err = soap_s2double(soap, soap_value(soap), p);
16903  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16904  return NULL;
16905  }
16906  else
16907  {
16908  p = (double*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(double), 0, NULL, NULL);
16909  if (soap->body && soap_element_end_in(soap, tag))
16910  return NULL;
16911  }
16912  return p;
16913 }
16914 
16915 /******************************************************************************/
16916 
16917 SOAP_FMAC1
16918 const char*
16919 SOAP_FMAC2
16920 soap_unsignedByte2s(struct soap *soap, unsigned char n)
16921 {
16922  return soap_unsignedLong2s(soap, (unsigned long)n);
16923 }
16924 
16925 /******************************************************************************/
16926 
16927 SOAP_FMAC1
16928 int
16929 SOAP_FMAC2
16930 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
16931 {
16932  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
16933  || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
16934  return soap->error;
16935  return soap_element_end_out(soap, tag);
16936 }
16937 
16938 /******************************************************************************/
16939 
16940 SOAP_FMAC1
16941 int
16942 SOAP_FMAC2
16943 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
16944 {
16945  if (s)
16946  {
16947  long n;
16948  char *r;
16949  if (!*s)
16950  return soap->error = SOAP_EMPTY;
16951  n = soap_strtol(s, &r, 10);
16952  if (s == r || *r || n < 0 || n > 255)
16953  soap->error = SOAP_TYPE;
16954  *p = (unsigned char)n;
16955  }
16956  return soap->error;
16957 }
16958 
16959 /******************************************************************************/
16960 
16961 SOAP_FMAC1
16962 unsigned char *
16963 SOAP_FMAC2
16964 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
16965 {
16966  if (soap_element_begin_in(soap, tag, 0, NULL))
16967  return NULL;
16968 #ifndef WITH_LEAN
16969  if (*soap->type
16971  && soap_match_tag(soap, soap->type, ":unsignedByte"))
16972  {
16973  soap->error = SOAP_TYPE;
16974  soap_revert(soap);
16975  return NULL;
16976  }
16977 #else
16978  (void)type;
16979 #endif
16980  p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), NULL, NULL, NULL, NULL);
16981  if (!p)
16982  return NULL;
16983  if (*soap->href != '#')
16984  {
16985  int err = soap_s2unsignedByte(soap, soap_value(soap), p);
16986  if ((soap->body && soap_element_end_in(soap, tag)) || err)
16987  return NULL;
16988  }
16989  else
16990  {
16991  p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned char), 0, NULL, NULL);
16992  if (soap->body && soap_element_end_in(soap, tag))
16993  return NULL;
16994  }
16995  return p;
16996 }
16997 
16998 /******************************************************************************/
16999 
17000 SOAP_FMAC1
17001 const char*
17002 SOAP_FMAC2
17003 soap_unsignedShort2s(struct soap *soap, unsigned short n)
17004 {
17005  return soap_unsignedLong2s(soap, (unsigned long)n);
17006 }
17007 
17008 /******************************************************************************/
17009 
17010 SOAP_FMAC1
17011 int
17012 SOAP_FMAC2
17013 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
17014 {
17015  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
17016  || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
17017  return soap->error;
17018  return soap_element_end_out(soap, tag);
17019 }
17020 
17021 /******************************************************************************/
17022 
17023 SOAP_FMAC1
17024 int
17025 SOAP_FMAC2
17026 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
17027 {
17028  if (s)
17029  {
17030  long n;
17031  char *r;
17032  if (!*s)
17033  return soap->error = SOAP_EMPTY;
17034  n = soap_strtol(s, &r, 10);
17035  if (s == r || *r || n < 0 || n > 65535)
17036  soap->error = SOAP_TYPE;
17037  *p = (unsigned short)n;
17038  }
17039  return soap->error;
17040 }
17041 
17042 /******************************************************************************/
17043 
17044 SOAP_FMAC1
17045 unsigned short *
17046 SOAP_FMAC2
17047 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
17048 {
17049  if (soap_element_begin_in(soap, tag, 0, NULL))
17050  return NULL;
17051 #ifndef WITH_LEAN
17052  if (*soap->type
17054  && soap_match_tag(soap, soap->type, ":unsignedShort")
17055  && soap_match_tag(soap, soap->type, ":unsignedByte"))
17056  {
17057  soap->error = SOAP_TYPE;
17058  soap_revert(soap);
17059  return NULL;
17060  }
17061 #else
17062  (void)type;
17063 #endif
17064  p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), NULL, NULL, NULL, NULL);
17065  if (!p)
17066  return NULL;
17067  if (*soap->href != '#')
17068  {
17069  int err = soap_s2unsignedShort(soap, soap_value(soap), p);
17070  if ((soap->body && soap_element_end_in(soap, tag)) || err)
17071  return NULL;
17072  }
17073  else
17074  {
17075  p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned short), 0, NULL, NULL);
17076  if (soap->body && soap_element_end_in(soap, tag))
17077  return NULL;
17078  }
17079  return p;
17080 }
17081 
17082 /******************************************************************************/
17083 
17084 SOAP_FMAC1
17085 const char*
17086 SOAP_FMAC2
17087 soap_unsignedInt2s(struct soap *soap, unsigned int n)
17088 {
17089  return soap_unsignedLong2s(soap, (unsigned long)n);
17090 }
17091 
17092 /******************************************************************************/
17093 
17094 SOAP_FMAC1
17095 int
17096 SOAP_FMAC2
17097 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
17098 {
17099  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
17100  || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
17101  return soap->error;
17102  return soap_element_end_out(soap, tag);
17103 }
17104 
17105 /******************************************************************************/
17106 
17107 SOAP_FMAC1
17108 int
17109 SOAP_FMAC2
17110 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
17111 {
17112  if (s)
17113  {
17114  char *r;
17115  if (!*s)
17116  return soap->error = SOAP_EMPTY;
17117 #ifndef WITH_NOIO
17118 #ifndef WITH_LEAN
17120 #endif
17121 #endif
17122  *p = (unsigned int)soap_strtoul(s, &r, 10);
17123  if (s == r || *r
17124 #ifndef WITH_NOIO
17125 #ifndef WITH_LEAN
17126  || soap_errno == SOAP_ERANGE
17127 #endif
17128 #endif
17129  )
17130  soap->error = SOAP_TYPE;
17131 #ifdef HAVE_STRTOUL
17132  if (*p > 0 && strchr(s, '-'))
17133  return soap->error = SOAP_TYPE;
17134 #endif
17135  }
17136  return soap->error;
17137 }
17138 
17139 /******************************************************************************/
17140 
17141 SOAP_FMAC1
17142 unsigned int *
17143 SOAP_FMAC2
17144 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
17145 {
17146  if (soap_element_begin_in(soap, tag, 0, NULL))
17147  return NULL;
17148 #ifndef WITH_LEAN
17149  if (*soap->type
17151  && soap_match_tag(soap, soap->type, ":unsignedInt")
17152  && soap_match_tag(soap, soap->type, ":unsignedShort")
17153  && soap_match_tag(soap, soap->type, ":unsignedByte"))
17154  {
17155  soap->error = SOAP_TYPE;
17156  soap_revert(soap);
17157  return NULL;
17158  }
17159 #else
17160  (void)type;
17161 #endif
17162  p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), NULL, NULL, NULL, NULL);
17163  if (!p)
17164  return NULL;
17165  if (*soap->href != '#')
17166  {
17167  int err = soap_s2unsignedInt(soap, soap_value(soap), p);
17168  if ((soap->body && soap_element_end_in(soap, tag)) || err)
17169  return NULL;
17170  }
17171  else
17172  {
17173  p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned int), 0, NULL, NULL);
17174  if (soap->body && soap_element_end_in(soap, tag))
17175  return NULL;
17176  }
17177  return p;
17178 }
17179 
17180 /******************************************************************************/
17181 
17182 SOAP_FMAC1
17183 const char*
17184 SOAP_FMAC2
17185 soap_unsignedLong2s(struct soap *soap, unsigned long n)
17186 {
17187  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "%lu", n);
17188  return soap->tmpbuf;
17189 }
17190 
17191 /******************************************************************************/
17192 
17193 SOAP_FMAC1
17194 int
17195 SOAP_FMAC2
17196 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
17197 {
17198  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
17200  return soap->error;
17201  return soap_element_end_out(soap, tag);
17202 }
17203 
17204 /******************************************************************************/
17205 
17206 SOAP_FMAC1
17207 int
17208 SOAP_FMAC2
17209 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
17210 {
17211  if (s)
17212  {
17213  char *r;
17214  if (!*s)
17215  return soap->error = SOAP_EMPTY;
17216 #ifndef WITH_NOIO
17217 #ifndef WITH_LEAN
17219 #endif
17220 #endif
17221  *p = soap_strtoul(s, &r, 10);
17222  if (s == r || *r
17223 #ifndef WITH_NOIO
17224 #ifndef WITH_LEAN
17225  || soap_errno == SOAP_ERANGE
17226 #endif
17227 #endif
17228  )
17229  soap->error = SOAP_TYPE;
17230 #ifdef HAVE_STRTOUL
17231  if (*p > 0 && strchr(s, '-'))
17232  return soap->error = SOAP_TYPE;
17233 #endif
17234  }
17235  return soap->error;
17236 }
17237 
17238 /******************************************************************************/
17239 
17240 SOAP_FMAC1
17241 unsigned long *
17242 SOAP_FMAC2
17243 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
17244 {
17245  if (soap_element_begin_in(soap, tag, 0, NULL))
17246  return NULL;
17247 #ifndef WITH_LEAN
17248  if (*soap->type
17250  && soap_match_tag(soap, soap->type, ":unsignedInt")
17251  && soap_match_tag(soap, soap->type, ":unsignedShort")
17252  && soap_match_tag(soap, soap->type, ":unsignedByte"))
17253  {
17254  soap->error = SOAP_TYPE;
17255  soap_revert(soap);
17256  return NULL;
17257  }
17258 #else
17259  (void)type;
17260 #endif
17261  p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), NULL, NULL, NULL, NULL);
17262  if (!p)
17263  return NULL;
17264  if (*soap->href != '#')
17265  {
17266  int err = soap_s2unsignedLong(soap, soap_value(soap), p);
17267  if ((soap->body && soap_element_end_in(soap, tag)) || err)
17268  return NULL;
17269  }
17270  else
17271  {
17272  p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(unsigned long), 0, NULL, NULL);
17273  if (soap->body && soap_element_end_in(soap, tag))
17274  return NULL;
17275  }
17276  return p;
17277 }
17278 
17279 /******************************************************************************/
17280 
17281 SOAP_FMAC1
17282 const char*
17283 SOAP_FMAC2
17285 {
17286  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), SOAP_ULONG_FORMAT, n);
17287  return soap->tmpbuf;
17288 }
17289 
17290 /******************************************************************************/
17291 
17292 SOAP_FMAC1
17293 int
17294 SOAP_FMAC2
17295 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
17296 {
17297  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
17298  || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
17299  return soap->error;
17300  return soap_element_end_out(soap, tag);
17301 }
17302 
17303 /******************************************************************************/
17304 
17305 SOAP_FMAC1
17306 int
17307 SOAP_FMAC2
17308 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
17309 {
17310  if (s)
17311  {
17312  char *r;
17313  if (!*s)
17314  return soap->error = SOAP_EMPTY;
17315 #ifndef WITH_NOIO
17316 #ifndef WITH_LEAN
17318 #endif
17319 #endif
17320  *p = soap_strtoull(s, &r, 10);
17321  if (s == r || *r
17322 #ifndef WITH_NOIO
17323 #ifndef WITH_LEAN
17324  || soap_errno == SOAP_ERANGE
17325 #endif
17326 #endif
17327  )
17328  soap->error = SOAP_TYPE;
17329  if (*p > 0 && strchr(s, '-'))
17330  return soap->error = SOAP_TYPE;
17331  }
17332  return soap->error;
17333 }
17334 
17335 /******************************************************************************/
17336 
17337 SOAP_FMAC1
17338 ULONG64 *
17339 SOAP_FMAC2
17340 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
17341 {
17342  if (soap_element_begin_in(soap, tag, 0, NULL))
17343  return NULL;
17344 #ifndef WITH_LEAN
17345  if (*soap->type
17347  && soap_match_tag(soap, soap->type, ":positiveInteger")
17348  && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
17349  && soap_match_tag(soap, soap->type, ":unsignedLong")
17350  && soap_match_tag(soap, soap->type, ":unsignedInt")
17351  && soap_match_tag(soap, soap->type, ":unsignedShort")
17352  && soap_match_tag(soap, soap->type, ":unsignedByte"))
17353  {
17354  soap->error = SOAP_TYPE;
17355  soap_revert(soap);
17356  return NULL;
17357  }
17358 #else
17359  (void)type;
17360 #endif
17361  p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), NULL, NULL, NULL, NULL);
17362  if (!p)
17363  return NULL;
17364  if (*soap->href != '#')
17365  {
17366  int err = soap_s2ULONG64(soap, soap_value(soap), p);
17367  if ((soap->body && soap_element_end_in(soap, tag)) || err)
17368  return NULL;
17369  }
17370  else
17371  {
17372  p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(ULONG64), 0, NULL, NULL);
17373  if (soap->body && soap_element_end_in(soap, tag))
17374  return NULL;
17375  }
17376  return p;
17377 }
17378 
17379 /******************************************************************************/
17380 
17381 SOAP_FMAC1
17382 int
17383 SOAP_FMAC2
17384 soap_s2char(struct soap *soap, const char *s, char **t, int flag, long minlen, long maxlen, const char *pattern)
17385 {
17386  if (s)
17387  {
17388  const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern);
17389  if (r && (*t = soap_strdup(soap, r)) == NULL)
17390  return soap->error = SOAP_EOM;
17391  }
17392  return soap->error;
17393 }
17394 
17395 /******************************************************************************/
17396 
17397 #ifndef WITH_COMPAT
17398 #ifdef __cplusplus
17399 SOAP_FMAC1
17400 int
17401 SOAP_FMAC2
17402 soap_s2stdchar(struct soap *soap, const char *s, std::string *t, int flag, long minlen, long maxlen, const char *pattern)
17403 {
17404  if (s)
17405  {
17406  const char *r = soap_string(soap, s, flag, minlen, maxlen, pattern);
17407  if (r)
17408  t->assign(r);
17409  }
17410  return soap->error;
17411 }
17412 #endif
17413 #endif
17414 
17415 /******************************************************************************/
17416 
17417 static const char*
17418 soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern)
17419 {
17420  if (s)
17421  {
17422  if (maxlen < 0 && soap->maxlength > 0)
17423  maxlen = soap->maxlength;
17424  if (minlen > 0 || maxlen >= 0)
17425  {
17426  size_t l;
17427  if ((soap->mode & SOAP_C_UTFSTRING))
17428  l = soap_utf8len(s);
17429  else
17430  l = strlen(s);
17431  if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen))
17432  {
17433  soap->error = SOAP_LENGTH;
17434  return NULL;
17435  }
17436  }
17437  if (flag >= 4)
17438  s = soap_collapse(soap, (char*)s, flag, 0);
17439 #ifndef WITH_LEANER
17440  if (pattern && soap->fsvalidate)
17441  {
17442  soap->error = soap->fsvalidate(soap, pattern, s);
17443  if (soap->error)
17444  return NULL;
17445  }
17446 #else
17447  (void)pattern;
17448 #endif
17449  }
17450  return s;
17451 }
17452 
17453 /******************************************************************************/
17454 
17455 static char*
17456 soap_collapse(struct soap *soap, char *s, int flag, int insitu)
17457 {
17458  /* flag 4=normalizedString (replace), 5=token (collapse) */
17459  char *t;
17460  size_t n;
17461  if (!s)
17462  return NULL;
17463  if (flag == 4)
17464  {
17465  for (t = s; *t && (!soap_coblank((soap_wchar)*t) || *t == 32); t++)
17466  continue;
17467  if (*t)
17468  {
17469  /* replace white space and control chars by blanks */
17470  if (!insitu)
17471  s = soap_strdup(soap, s);
17472  for (t = s; *t; t++)
17473  if (soap_coblank((soap_wchar)*t))
17474  *t = ' ';
17475  }
17476  return s;
17477  }
17478  /* collapse white space */
17479  for (t = s; *t && soap_coblank((soap_wchar)*t); t++)
17480  continue;
17481  n = strlen(t);
17482  if (insitu && s < t)
17483  (void)soap_memmove(s, n + 1, t, n + 1);
17484  else
17485  s = t;
17486  if (n > 0)
17487  {
17488  if (!soap_coblank((soap_wchar)s[n-1]))
17489  {
17490  for (t = s; (*t && !soap_coblank((soap_wchar)*t)) || (*t == 32 && (!t[1] || !soap_coblank((soap_wchar)t[1]))); t++)
17491  continue;
17492  if (!*t)
17493  return s;
17494  }
17495  if (!insitu)
17496  s = soap_strdup(soap, s);
17497  for (t = s; *t; t++)
17498  {
17499  if (soap_coblank((soap_wchar)*t))
17500  {
17501  char *r;
17502  *t = ' ';
17503  for (r = t + 1; *r && soap_coblank((soap_wchar)*r); r++)
17504  continue;
17505  if (r > t + 1)
17506  (void)soap_memmove(t + 1, n - (t-s), r, n - (r-s) + 1);
17507  }
17508  }
17509  t--;
17510  if (t >= s && *t == 32)
17511  *t = '\0';
17512  }
17513  return s;
17514 }
17515 
17516 /******************************************************************************/
17517 
17518 SOAP_FMAC1
17519 int
17520 SOAP_FMAC2
17521 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen, const char *pattern)
17522 {
17523  *t = NULL;
17524  if (s)
17525  {
17526  const char *r = soap_QName(soap, s, minlen, maxlen, pattern);
17527  if (r && (*t = soap_strdup(soap, r)) == NULL)
17528  return soap->error = SOAP_EOM;
17529  }
17530  return soap->error;
17531 }
17532 
17533 /******************************************************************************/
17534 
17535 #ifndef WITH_COMPAT
17536 #ifdef __cplusplus
17537 SOAP_FMAC1
17538 int
17539 SOAP_FMAC2
17540 soap_s2stdQName(struct soap *soap, const char *s, std::string *t, long minlen, long maxlen, const char *pattern)
17541 {
17542  t->clear();
17543  if (s)
17544  {
17545  const char *r = soap_QName(soap, s, minlen, maxlen, pattern);
17546  if (r)
17547  t->assign(r);
17548  }
17549  return soap->error;
17550 }
17551 #endif
17552 #endif
17553 
17554 /******************************************************************************/
17555 
17556 static const char*
17557 soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern)
17558 {
17559  if (s)
17560  {
17561  char *b;
17562  if (maxlen < 0 && soap->maxlength > 0)
17563  maxlen = soap->maxlength;
17564  if (minlen > 0 || maxlen >= 0)
17565  {
17566  size_t l;
17567  if ((soap->mode & SOAP_C_UTFSTRING))
17568  l = soap_utf8len(s);
17569  else
17570  l = strlen(s);
17571  if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen))
17572  {
17573  soap->error = SOAP_LENGTH;
17574  return NULL;
17575  }
17576  }
17577 #ifdef WITH_FAST
17578  soap->labidx = 0;
17579 #else
17580  if (soap_alloc_block(soap) == NULL)
17581  return NULL;
17582 #endif
17583  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
17584  /* convert (by prefix normalize prefix) all QNames in s */
17585  for (;;)
17586  {
17587  size_t n;
17588  struct soap_nlist *np;
17589  const char *p = NULL;
17590  short flag = 0;
17591  const char *r = NULL;
17592  size_t m = 0;
17593 #ifndef WITH_FAST
17594  size_t k = 0;
17595 #endif
17596  /* skip blanks */
17597  while (*s && soap_coblank((soap_wchar)*s))
17598  s++;
17599  if (!*s)
17600  break;
17601  /* find next QName */
17602  n = 1;
17603  while (s[n] && !soap_coblank((soap_wchar)s[n]))
17604  n++;
17605  np = soap->nlist;
17606  /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
17607  if (!np || *s == '#' || !strncmp(s, "xml:", 4))
17608  {
17609  r = s;
17610  m = n;
17611  }
17612  else /* we normalize the QName by replacing its prefix */
17613  {
17614  const char *q;
17615  for (p = s; *p && p < s + n; p++)
17616  if (*p == ':')
17617  break;
17618  if (*p == ':')
17619  {
17620  size_t k = p - s;
17621  while (np && (strncmp(np->id, s, k) || np->id[k]))
17622  np = np->next;
17623  p++;
17624  }
17625  else
17626  {
17627  while (np && *np->id)
17628  np = np->next;
17629  p = s;
17630  }
17631  /* replace prefix */
17632  if (np)
17633  {
17634  if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id) != NULL)
17635  {
17636  size_t k = strlen(q);
17637  if (q[k-1] != '_')
17638  {
17639  r = q;
17640  m = k;
17641  }
17642  else
17643  {
17644  flag = 1;
17645  r = soap->local_namespaces[np->index].ns;
17646  m = strlen(r);
17647  }
17648  }
17649  else if (np->ns)
17650  {
17651  flag = 1;
17652  r = np->ns;
17653  m = strlen(r);
17654  }
17655  else
17656  {
17657  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s, np->index, np->ns ? np->ns : SOAP_STR_EOS));
17659  return NULL;
17660  }
17661  }
17662  else if (s[n]) /* no namespace, part of string */
17663  {
17664  r = s;
17665  m = n;
17666  }
17667  else /* no namespace: assume "" namespace */
17668  {
17669  flag = 1;
17670  }
17671  }
17672 #ifdef WITH_FAST
17673  if ((flag && soap_append_lab(soap, "\"", 1))
17674  || (m && soap_append_lab(soap, r, m))
17675  || (flag && soap_append_lab(soap, "\"", 1))
17676  || (p && (soap_append_lab(soap, ":", 1) || soap_append_lab(soap, p, n - (p-s)))))
17677  return NULL;
17678 #else
17679  k = 2*flag + m + (p ? n - (p-s) + 1 : 0) + (s[n] != '\0');
17680  b = (char*)soap_push_block(soap, NULL, k);
17681  if (!b)
17682  return NULL;
17683  if (flag)
17684  *b++ = '"';
17685  if (m)
17686  {
17687  if (soap_memcpy((void*)b, k, (const void*)r, m))
17688  {
17689  soap->error = SOAP_EOM;
17690  return NULL;
17691  }
17692  b += m;
17693  }
17694  if (flag)
17695  *b++ = '"';
17696  if (p)
17697  {
17698  *b++ = ':';
17699  if (soap_memcpy((void*)b, k - m - flag - 1, (const void*)p, n - (p-s)))
17700  {
17701  soap->error = SOAP_EOM;
17702  return NULL;
17703  }
17704  b += n - (p-s);
17705  }
17706 #endif
17707  /* advance to next and add spacing */
17708  s += n;
17709  while (*s && soap_coblank(*s))
17710  s++;
17711  if (*s)
17712  {
17713 #ifdef WITH_FAST
17714  if (soap_append_lab(soap, " ", 1))
17715  return NULL;
17716 #else
17717  *b = ' ';
17718 #endif
17719  }
17720  }
17721 #ifdef WITH_FAST
17723  return NULL;
17724  b = soap->labbuf;
17725 #else
17726  b = (char*)soap_push_block(soap, NULL, 1);
17727  if (!b)
17728  return NULL;
17729  *b = '\0';
17730  b = (char*)soap_save_block(soap, NULL, NULL, 0);
17731 #endif
17732 #ifndef WITH_LEANER
17733  if (pattern && soap->fsvalidate)
17734  {
17735  soap->error = soap->fsvalidate(soap, pattern, b);
17736  if (soap->error)
17737  return NULL;
17738  }
17739 #else
17740  (void)pattern;
17741 #endif
17742  return b;
17743  }
17744  return NULL;
17745 }
17746 
17747 /******************************************************************************/
17748 
17749 SOAP_FMAC1
17750 const char*
17751 SOAP_FMAC2
17752 soap_QName2s(struct soap *soap, const char *s)
17753 {
17754  const char *t = NULL;
17755  if (s)
17756  {
17757 #ifdef WITH_FAST
17759  soap->labidx = 0;
17760 #else
17761  char *b = NULL;
17762  if (soap_alloc_block(soap) == NULL)
17763  return NULL;
17764 #endif
17765  for (;;)
17766  {
17767  size_t n;
17768  const char *q = NULL;
17769  const char *r = NULL;
17770  size_t m = 0;
17771 #ifndef WITH_FAST
17772  size_t k = 0;
17773 #endif
17774  /* skip blanks */
17775  while (*s && soap_coblank((soap_wchar)*s))
17776  s++;
17777  if (!*s)
17778  {
17779 #ifdef WITH_FAST
17780  soap->labbuf[soap->labidx > 0 ? soap->labidx - 1 : 0] = '\0';
17781 #else
17782  if (!b)
17783  return soap_strdup(soap, SOAP_STR_EOS);
17784  --b;
17785  *b = '\0';
17786 #endif
17787  break;
17788  }
17789  /* find next QName */
17790  n = 0;
17791  while (s[n] && !soap_coblank((soap_wchar)s[n]))
17792  {
17793  if (s[n] == ':')
17794  r = s;
17795  n++;
17796  }
17797  if (*s != '"') /* non-quoted: pass string as is */
17798  {
17799 #ifndef WITH_LEAN
17800  if (r && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_XML_CANONICAL_NA))
17801  soap_utilize_ns(soap, s, 1);
17802 #endif
17803  r = s;
17804  m = n + 1;
17805  }
17806  else /* prefix quoted URI-based string */
17807  {
17808  q = strchr(s + 1, '"');
17809  if (q)
17810  {
17811  struct Namespace *p = soap->local_namespaces;
17812  if (p)
17813  {
17814  for (; p->id; p++)
17815  {
17816  if (p->ns)
17817  if (!soap_tag_cmp(s + 1, p->ns))
17818  break;
17819  if (p->in)
17820  if (!soap_tag_cmp(s + 1, p->in))
17821  break;
17822  }
17823  }
17824  q++;
17825  /* URL is in the namespace table? */
17826  if (p && p->id)
17827  {
17828  r = p->id;
17829  m = strlen(r);
17830  }
17831  else /* not in namespace table: create xmlns binding */
17832  {
17833  char *x = soap_strdup(soap, s + 1);
17834  if (!x)
17835  return NULL;
17836  x[q - s - 2] = '\0';
17837  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 27), "xmlns:_%d", soap->idnum++);
17838  soap_set_attr(soap, soap->tmpbuf, x, 1);
17839  r = soap->tmpbuf + 6;
17840  m = strlen(r);
17841  }
17842  }
17843  }
17844  /* copy normalized QName into buffer, including the ending blank or NUL */
17845 #ifdef WITH_FAST
17846  if ((m && soap_append_lab(soap, r, m))
17847  || (q && soap_append_lab(soap, q, n - (q - s) + 1)))
17848  return NULL;
17849 #else
17850  k = m + (q ? n - (q - s) + 1 : 0);
17851  b = (char*)soap_push_block(soap, NULL, k);
17852  if (!b)
17853  {
17854  soap->error = SOAP_EOM;
17855  return NULL;
17856  }
17857  if (soap_memcpy((void*)b, k, (const void*)r, m))
17858  {
17859  soap->error = SOAP_EOM;
17860  return NULL;
17861  }
17862  b += m;
17863  if (q)
17864  {
17865  if (soap_memcpy((void*)b, k - m, (const void*)q, n - (q - s) + 1))
17866  {
17867  soap->error = SOAP_EOM;
17868  return NULL;
17869  }
17870  b += n - (q - s) + 1;
17871  }
17872 #endif
17873  /* advance to next */
17874  s += n;
17875  }
17876 #ifdef WITH_FAST
17877  t = soap_strdup(soap, soap->labbuf);
17878  if (!t)
17879  soap->error = SOAP_EOM;
17880 #else
17881  t = (char*)soap_save_block(soap, NULL, NULL, 0);
17882 #endif
17883  }
17884  return t;
17885 }
17886 
17887 /******************************************************************************/
17888 
17889 #ifndef WITH_LEAN
17890 SOAP_FMAC1
17891 int
17892 SOAP_FMAC2
17893 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, int flag, long minlen, long maxlen, const char *pattern)
17894 {
17895  if (s)
17896  {
17897  const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern);
17898  if (r && (*t = soap_wstrdup(soap, r)) == NULL)
17899  return soap->error = SOAP_EOM;
17900  }
17901  return soap->error;
17902 }
17903 #endif
17904 
17905 /******************************************************************************/
17906 
17907 #ifndef WITH_COMPAT
17908 #ifdef __cplusplus
17909 #ifndef WITH_LEAN
17910 SOAP_FMAC1
17911 int
17912 SOAP_FMAC2
17913 soap_s2stdwchar(struct soap *soap, const char *s, std::wstring *t, int flag, long minlen, long maxlen, const char *pattern)
17914 {
17915  if (s)
17916  {
17917  const wchar_t *r = soap_wstring(soap, s, flag, minlen, maxlen, pattern);
17918  if (r)
17919  t->assign(r);
17920  }
17921  return soap->error;
17922 }
17923 #endif
17924 #endif
17925 #endif
17926 
17927 /******************************************************************************/
17928 
17929 #ifndef WITH_LEAN
17930 static const wchar_t*
17931 soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern)
17932 {
17933  if (s)
17934  {
17935  size_t l;
17936  soap_wchar c;
17937  wchar_t *t;
17938  if (maxlen < 0 && soap->maxlength > 0)
17939  maxlen = soap->maxlength;
17940  soap->labidx = 0;
17941  if ((soap->mode & SOAP_ENC_LATIN))
17942  {
17943  wchar_t *r;
17944  if (soap_append_lab(soap, NULL, sizeof(wchar_t) * (strlen(s) + 1)))
17945  return NULL;
17946  r = (wchar_t*)soap->labbuf;
17947  while (*s)
17948  *r++ = (wchar_t)*s++;
17949  }
17950  else
17951  {
17952  /* Convert UTF8 to wchar_t */
17953  while (*s)
17954  {
17955  c = (unsigned char)*s++;
17956  if (c >= 0x80)
17957  {
17958 #ifdef WITH_REPLACE_ILLEGAL_UTF8
17959  soap_wchar c1, c2, c3;
17960  c1 = (unsigned char)*s;
17961  if (c <= 0xC1 || (c1 & 0xC0) != 0x80)
17962  {
17963  c = SOAP_UNKNOWN_UNICODE_CHAR;
17964  }
17965  else
17966  {
17967  ++s;
17968  c1 &= 0x3F;
17969  if (c < 0xE0)
17970  {
17971  c = (((c & 0x1F) << 6) | c1);
17972  }
17973  else
17974  {
17975  c2 = (unsigned char)*s;
17976  if ((c == 0xE0 && c1 < 0x20) || (c2 & 0xC0) != 0x80)
17977  {
17978  c = SOAP_UNKNOWN_UNICODE_CHAR;
17979  }
17980  else
17981  {
17982  ++s;
17983  c2 &= 0x3F;
17984  if (c < 0xF0)
17985  {
17986  c = (((c & 0x0F) << 12) | (c1 << 6) | c2);
17987  }
17988  else
17989  {
17990  c3 = (unsigned char)*s;
17991  if ((c == 0xF0 && c1 < 0x10) || (c == 0xF4 && c1 >= 0x10) || c >= 0xF5 || (c3 & 0xC0) != 0x80)
17992  {
17993  c = SOAP_UNKNOWN_UNICODE_CHAR;
17994  }
17995  else
17996  {
17997  ++s;
17998  c = (((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | (c3 & 0x3F));
17999  }
18000  }
18001  }
18002  }
18003  }
18004 #else
18005  soap_wchar c1, c2, c3, c4;
18006  c1 = (unsigned char)*s;
18007  if (c1)
18008  {
18009  s++;
18010  c1 &= 0x3F;
18011  if (c < 0xE0)
18012  {
18013  c = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
18014  }
18015  else
18016  {
18017  c2 = (unsigned char)*s;
18018  if (c2)
18019  {
18020  s++;
18021  c2 &= 0x3F;
18022  if (c < 0xF0)
18023  {
18024  c = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
18025  }
18026  else
18027  {
18028  c3 = (unsigned char)*s;
18029  if (c3)
18030  {
18031  s++;
18032  c3 &= 0x3F;
18033  if (c < 0xF8)
18034  {
18035  c = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
18036  }
18037  else
18038  {
18039  c4 = (unsigned char)*s;
18040  if (c4)
18041  {
18042  s++;
18043  c4 &= 0x3F;
18044  if (c < 0xFC)
18045  {
18046  c = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
18047  }
18048  else
18049  {
18050  c = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (unsigned char)(*s & 0x3F));
18051  if (*s)
18052  s++;
18053  }
18054  }
18055  }
18056  }
18057  }
18058  }
18059  }
18060  }
18061 #endif
18062  }
18063  /* use UTF16 encoding when wchar_t is too small to hold UCS */
18064  if (sizeof(wchar_t) < 4 && c > 0xFFFF)
18065  {
18066  wchar_t c1, c2;
18067  c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
18068  c2 = 0xDC00 + (c & 0x3FF);
18069  if (soap_append_lab(soap, (const char*)&c1, sizeof(wchar_t)) || soap_append_lab(soap, (const char*)&c2, sizeof(wchar_t)))
18070  return NULL;
18071  }
18072  else if (soap_append_lab(soap, (const char*)&c, sizeof(wchar_t)))
18073  {
18074  return NULL;
18075  }
18076  }
18077  }
18078  l = soap->labidx / sizeof(wchar_t);
18079  c = L'\0';
18080  if (soap_append_lab(soap, (const char*)&c, sizeof(wchar_t)))
18081  return NULL;
18082  if ((maxlen >= 0 && l > (size_t)maxlen) || (minlen > 0 && l < (size_t)minlen))
18083  {
18084  soap->error = SOAP_LENGTH;
18085  return NULL;
18086  }
18087  t = (wchar_t*)soap->labbuf;
18088 #ifndef WITH_LEAN
18089  if (flag >= 4 && t)
18090  t = soap_wcollapse(soap, t, flag, 1);
18091 #endif
18092 #ifndef WITH_LEANER
18093  if (pattern && soap->fwvalidate)
18094  {
18095  soap->error = soap->fwvalidate(soap, pattern, t);
18096  if (soap->error)
18097  return NULL;
18098  }
18099 #endif
18100  return t;
18101  }
18102  return NULL;
18103 }
18104 #endif
18105 
18106 /******************************************************************************/
18107 
18108 #ifndef WITH_LEAN
18109 static wchar_t*
18110 soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu)
18111 {
18112  /* flag 4=normalizedString (replace), 5=token (collapse) */
18113  wchar_t *t;
18114  size_t n;
18115  if (!s)
18116  return NULL;
18117  if (flag == 4)
18118  {
18119  for (t = s; *t && (!soap_coblank((soap_wchar)*t) || *t == 32); t++)
18120  continue;
18121  if (*t)
18122  {
18123  /* replace blanks and control char by space */
18124  if (!insitu)
18125  s = soap_wstrdup(soap, s);
18126  if (s)
18127  for (t = s; *t; t++)
18128  if (soap_coblank((soap_wchar)*t))
18129  *t = L' ';
18130  }
18131  return s;
18132  }
18133  /* collapse white space */
18134  for (t = s; *t && soap_coblank((soap_wchar)*t); t++)
18135  continue;
18136  n = 0;
18137  while (t[n])
18138  n++;
18139  if (insitu && s < t)
18140  (void)soap_memmove(s, n + 1, t, n + 1);
18141  else
18142  s = t;
18143  if (n > 0)
18144  {
18145  if (!soap_coblank((soap_wchar)s[n-1]))
18146  {
18147  for (t = s; (*t && !soap_coblank((soap_wchar)*t)) || (*t == 32 && (!t[1] || !soap_coblank((soap_wchar)t[1]))); t++)
18148  continue;
18149  if (!*t)
18150  return s;
18151  }
18152  if (!insitu)
18153  s = soap_wstrdup(soap, s);
18154  if (s)
18155  {
18156  for (t = s; *t; t++)
18157  {
18158  if (soap_coblank((soap_wchar)*t))
18159  {
18160  wchar_t *r;
18161  *t = L' ';
18162  for (r = t + 1; *r && soap_coblank((soap_wchar)*r); r++)
18163  continue;
18164  if (r > t + 1)
18165  (void)soap_memmove(t + 1, sizeof(wchar_t) * (n - (t-s)), r, sizeof(wchar_t) * (n - (r-s) + 1));
18166  }
18167  }
18168  t--;
18169  if (t >= s && *t == 32)
18170  *t = L'\0';
18171  }
18172  }
18173  return s;
18174 }
18175 #endif
18176 
18177 /******************************************************************************/
18178 
18179 #ifndef WITH_LEAN
18180 SOAP_FMAC1
18181 const char*
18182 SOAP_FMAC2
18183 soap_wchar2s(struct soap *soap, const wchar_t *s)
18184 {
18185  soap_wchar c;
18186  char *r, *t;
18187  const wchar_t *q = s;
18188  size_t n = 0;
18189  if (!s)
18190  return NULL;
18191  while ((c = *q++))
18192  {
18193  if (c > 0 && c < 0x80)
18194  n++;
18195  else
18196 #ifdef WITH_REPLACE_ILLEGAL_UTF8
18197  n += 4;
18198 #else
18199  n += 6;
18200 #endif
18201  }
18202  r = t = (char*)soap_malloc(soap, n + 1);
18203  if (r)
18204  {
18205  /* Convert wchar to UTF8 (chars above U+10FFFF are silently converted, but should not be used) */
18206  while ((c = *s++))
18207  {
18208  if (c > 0 && c < 0x80)
18209  {
18210  *t++ = (char)c;
18211  }
18212  else
18213  {
18214  /* check for UTF16 encoding when wchar_t is too small to hold UCS */
18215  if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
18216  {
18217  soap_wchar d = *s;
18218  if ((d & 0xFC00) == 0xDC00)
18219  {
18220  c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
18221  s++;
18222  }
18223 #ifdef WITH_REPLACE_ILLEGAL_UTF8
18224  else
18225  {
18226  c = SOAP_UNKNOWN_UNICODE_CHAR; /* Malformed UTF-16 */
18227  }
18228 #endif
18229  }
18230  if (c < 0x0800)
18231  {
18232  *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
18233  }
18234  else
18235  {
18236 #ifdef WITH_REPLACE_ILLEGAL_UTF8
18237  if (!((c >= 0x80 && c <= 0xD7FF) || (c >= 0xE000 && c <= 0xFFFD) || (c >= 0x10000 && c <= 0x10FFFF)))
18238  c = SOAP_UNKNOWN_UNICODE_CHAR;
18239 #endif
18240  if (c < 0x010000)
18241  {
18242  *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
18243  }
18244  else
18245  {
18246  if (c < 0x200000)
18247  {
18248  *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
18249  }
18250  else
18251  {
18252  if (c < 0x04000000)
18253  {
18254  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
18255  }
18256  else
18257  {
18258  *t++ = (char)(0xFC | ((c >> 30) & 0x01));
18259  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
18260  }
18261  *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
18262  }
18263  *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
18264  }
18265  *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
18266  }
18267  *t++ = (char)(0x80 | (c & 0x3F));
18268  }
18269  }
18270  *t = '\0';
18271  }
18272  return r;
18273 }
18274 #endif
18275 
18276 /******************************************************************************/
18277 
18278 SOAP_FMAC1
18279 int
18280 SOAP_FMAC2
18281 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
18282 {
18283  id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL);
18284  if (id < 0)
18285  return soap->error;
18286  if (!**p && (soap->mode & SOAP_C_NILSTRING))
18287  return soap_element_null(soap, tag, id, type);
18288  if (soap_element_begin_out(soap, tag, id, type)
18289  || soap_string_out(soap, *p, 0)
18290  || soap_element_end_out(soap, tag))
18291  return soap->error;
18292  return SOAP_OK;
18293 }
18294 
18295 /******************************************************************************/
18296 
18297 SOAP_FMAC1
18298 char **
18299 SOAP_FMAC2
18300 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern)
18301 {
18302  (void)type;
18303  if (soap_element_begin_in(soap, tag, 1, NULL))
18304  {
18305  if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
18306  return NULL;
18307  soap->error = SOAP_OK;
18308  }
18309  if (!p)
18310  {
18311  p = (char**)soap_malloc(soap, sizeof(char*));
18312  if (!p)
18313  return NULL;
18314  }
18315  if (soap->null)
18316  {
18317  *p = NULL;
18318  }
18319  else if (soap->body)
18320  {
18321  *p = soap_string_in(soap, flag, minlen, maxlen, pattern);
18322  if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), NULL, NULL, NULL, NULL))
18323  return NULL;
18324  if (!**p && tag && *tag == '-')
18325  {
18326  soap->error = SOAP_NO_TAG;
18327  return NULL;
18328  }
18329  }
18330  else if (tag && *tag == '-')
18331  {
18332  soap->error = SOAP_NO_TAG;
18333  return NULL;
18334  }
18335  else if (*soap->href != '#')
18336  {
18337  if (minlen > 0)
18338  {
18339  soap->error = SOAP_LENGTH;
18340  return NULL;
18341  }
18342  *p = soap_strdup(soap, SOAP_STR_EOS);
18343  if (!*p)
18344  return NULL;
18345  }
18346  if (*soap->href == '#')
18347  p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0, NULL);
18348  if (soap->body && soap_element_end_in(soap, tag))
18349  return NULL;
18350  return p;
18351 }
18352 
18353 /******************************************************************************/
18354 
18355 #ifndef WITH_LEANER
18356 SOAP_FMAC1
18357 int
18358 SOAP_FMAC2
18359 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
18360 {
18361  id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n, NULL);
18362  if (id < 0)
18363  return soap->error;
18364  if (!**p && (soap->mode & SOAP_C_NILSTRING))
18365  return soap_element_null(soap, tag, id, type);
18366  if (soap_element_begin_out(soap, tag, id, type)
18367  || soap_wstring_out(soap, *p, 0)
18368  || soap_element_end_out(soap, tag))
18369  return soap->error;
18370  return SOAP_OK;
18371 }
18372 #endif
18373 
18374 /******************************************************************************/
18375 
18376 #ifndef WITH_LEANER
18377 SOAP_FMAC1
18378 wchar_t **
18379 SOAP_FMAC2
18380 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern)
18381 {
18382  (void)type;
18383  if (soap_element_begin_in(soap, tag, 1, NULL))
18384  {
18385  if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
18386  return NULL;
18387  soap->error = SOAP_OK;
18388  }
18389  if (!p)
18390  {
18391  p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*));
18392  if (!p)
18393  return NULL;
18394  }
18395  if (soap->null)
18396  {
18397  *p = NULL;
18398  }
18399  else if (soap->body)
18400  {
18401  *p = soap_wstring_in(soap, flag, minlen, maxlen, pattern);
18402  if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), NULL, NULL, NULL, NULL))
18403  return NULL;
18404  if (!**p && tag && *tag == '-')
18405  {
18406  soap->error = SOAP_NO_TAG;
18407  return NULL;
18408  }
18409  }
18410  else if (tag && *tag == '-')
18411  {
18412  soap->error = SOAP_NO_TAG;
18413  return NULL;
18414  }
18415  else if (*soap->href != '#')
18416  {
18417  if (minlen > 0)
18418  {
18419  soap->error = SOAP_LENGTH;
18420  return NULL;
18421  }
18422  *p = soap_wstrdup(soap, L"");
18423  }
18424  if (*soap->href == '#')
18425  p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0, NULL);
18426  if (soap->body && soap_element_end_in(soap, tag))
18427  return NULL;
18428  return p;
18429 }
18430 #endif
18431 
18432 /******************************************************************************/
18433 
18434 #ifndef WITH_LEAN
18435 #ifdef UNDER_CE
18436 /* WinCE mktime (based on the mingw-runtime, public domain) */
18437 #define __FILETIME_to_ll(f) ((long long)(f).dwHighDateTime << 32 | (long long)(f).dwLowDateTime)
18438 static time_t
18439 mktime(struct tm *pt)
18440 {
18441  SYSTEMTIME s, s1, s2;
18442  FILETIME f, f1, f2;
18443  long long diff;
18444  GetSystemTime(&s1);
18445  GetLocalTime(&s2);
18446  SystemTimeToFileTime(&s1, &f1);
18447  SystemTimeToFileTime(&s2, &f2);
18448  diff = (__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL;
18449  s.wYear = pt->tm_year + 1900;
18450  s.wMonth = pt->tm_mon + 1;
18451  s.wDayOfWeek = pt->tm_wday;
18452  s.wDay = pt->tm_mday;
18453  s.wHour = pt->tm_hour;
18454  s.wMinute = pt->tm_min;
18455  s.wSecond = pt->tm_sec;
18456  s.wMilliseconds = 0;
18457  SystemTimeToFileTime(&s, &f);
18458  return (time_t)((__FILETIME_to_ll(f) - 116444736000000000LL) / 10000000LL) - (time_t)diff;
18459 }
18460 #endif
18461 #endif
18462 
18463 /******************************************************************************/
18464 
18465 #ifndef WITH_LEAN
18466 #ifdef UNDER_CE
18467 /* WinCE gmtime_r (based on the mingw-runtime, public domain) */
18468 #define HAVE_GMTIME_R
18469 static struct tm*
18470 gmtime_r(const time_t *t, struct tm *pt)
18471 {
18472  FILETIME f, f1, f2;
18473  SYSTEMTIME s, s1 = {0};
18474  long long time = (long long)(*t) * 10000000LL + 116444736000000000LL;
18475  f.dwHighDateTime = (DWORD)((time >> 32) & 0x00000000FFFFFFFF);
18476  f.dwLowDateTime = (DWORD)(time & 0x00000000FFFFFFFF);
18477  FileTimeToSystemTime(&f, &s);
18478  pt->tm_year = s.wYear - 1900;
18479  pt->tm_mon = s.wMonth - 1;
18480  pt->tm_wday = s.wDayOfWeek;
18481  pt->tm_mday = s.wDay;
18482  s1.wYear = s.wYear;
18483  s1.wMonth = 1;
18484  s1.wDayOfWeek = 1;
18485  s1.wDay = 1;
18486  SystemTimeToFileTime(&s1, &f1);
18487  SystemTimeToFileTime(&s, &f2);
18488  pt->tm_yday = (((__FILETIME_to_ll(f2) - __FILETIME_to_ll(f1)) / 10000000LL) / (60 * 60 * 24));
18489  pt->tm_hour = s.wHour;
18490  pt->tm_min = s.wMinute;
18491  pt->tm_sec = s.wSecond;
18492  pt->tm_isdst = 0;
18493  return pt;
18494 }
18495 #endif
18496 #endif
18497 
18498 /******************************************************************************/
18499 
18500 #ifndef WITH_LEAN
18501 #ifdef UNDER_CE
18502 /* WinCE very simple strftime for format "%Y-%m-%dT%H:%M:%SZ", note: %F and %T not supported by MS */
18503 static size_t
18504 strftime(char *buf, size_t len, const char *format, const struct tm *pT)
18505 {
18506  (void)len; (void)format;
18507 #ifndef WITH_NOZONE
18508  (SOAP_SNPRINTF(buf, len, 20), "%04d-%02d-%02dT%02d:%02d:%02dZ", pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec);
18509 #else
18510  (SOAP_SNPRINTF(buf, len, 20), "%04d-%02d-%02dT%02d:%02d:%02d", pT->tm_year + 1900, pT->tm_mon + 1, pT->tm_mday, pT->tm_hour, pT->tm_min, pT->tm_sec);
18511 #endif
18512  return len;
18513 }
18514 #endif
18515 #endif
18516 
18517 /******************************************************************************/
18518 
18519 #if !defined(WITH_LEAN) || defined(WITH_COOKIES)
18520 SOAP_FMAC1
18521 time_t
18522 SOAP_FMAC2
18523 soap_timegm(struct tm *T)
18524 {
18525 #if defined(HAVE_TIMEGM)
18526  return timegm(T);
18527 #else
18528  time_t t, g, z;
18529  struct tm tm;
18530 #ifndef HAVE_GMTIME_R
18531  struct tm *tp;
18532 #endif
18533  t = mktime(T);
18534  if (t == (time_t)-1)
18535  return (time_t)-1;
18536 #ifdef HAVE_GMTIME_R
18537  if (gmtime_r(&t, &tm) == SOAP_FUNC_R_ERR)
18538  return (time_t)-1;
18539 #else
18540  tp = gmtime(&t);
18541  if (!tp)
18542  return (time_t)-1;
18543  tm = *tp;
18544 #endif
18545  tm.tm_isdst = 0;
18546  g = mktime(&tm);
18547  if (g == (time_t)-1)
18548  return (time_t)-1;
18549  z = g - t;
18550  return t - z;
18551 #endif
18552 }
18553 #endif
18554 
18555 /******************************************************************************/
18556 
18557 #ifndef WITH_LEAN
18558 SOAP_FMAC1
18559 const char*
18560 SOAP_FMAC2
18561 soap_dateTime2s(struct soap *soap, time_t n)
18562 {
18563  struct tm T, *pT = &T;
18564  size_t l = 0;
18565 #if defined(HAVE_GMTIME_R) && !defined(WITH_NOZONE)
18566  if (gmtime_r(&n, pT) != SOAP_FUNC_R_ERR)
18567  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
18568 #elif defined(HAVE_GMTIME) && !defined(WITH_NOZONE)
18569  pT = gmtime(&n);
18570  if (pT)
18571  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
18572 #elif (defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)) && !defined(WITH_NOZONE)
18573 #if defined(HAVE_LOCALTIME_R)
18574  if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
18575  {
18576  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
18577  if (l)
18578  {
18579  (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
18580  soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
18581  }
18582  }
18583 #else
18584  pT = localtime(&n);
18585  if (pT)
18586  {
18587  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
18588  if (l)
18589  {
18590  (void)soap_memmove(soap->tmpbuf + 23, sizeof(soap->tmpbuf) - 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
18591  soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
18592  }
18593  }
18594 #endif
18595 #elif defined(HAVE_GETTIMEOFDAY) && !defined(WITH_NOZONE)
18596 #if defined(HAVE_LOCALTIME_R)
18597  if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
18598  {
18599  struct timeval tv;
18600  struct timezone tz;
18601  memset((void*)&tz, 0, sizeof(tz));
18602  gettimeofday(&tv, &tz);
18603  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
18604  if (l)
18605  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
18606  }
18607 #else
18608  pT = localtime(&n);
18609  if (pT)
18610  {
18611  struct timeval tv;
18612  struct timezone tz;
18613  memset((void*)&tz, 0, sizeof(tz));
18614  gettimeofday(&tv, &tz);
18615  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
18616  if (l)
18617  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
18618  }
18619 #endif
18620 #elif defined(HAVE_FTIME) && !defined(WITH_NOZONE)
18621 #if defined(HAVE_LOCALTIME_R)
18622  if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
18623  {
18624  struct timeb t;
18625  memset((void*)&t, 0, sizeof(t));
18626 #ifdef __BORLANDC__
18627  ::ftime(&t);
18628 #else
18629  ftime(&t);
18630 #endif
18631  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
18632  if (l)
18633  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
18634  }
18635 #else
18636  pT = localtime(&n);
18637  if (pT)
18638  {
18639  struct timeb t;
18640  memset((void*)&t, 0, sizeof(t));
18641 #ifdef __BORLANDC__
18642  ::ftime(&t);
18643 #else
18644  ftime(&t);
18645 #endif
18646  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
18647  if (l)
18648  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, 7), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
18649  }
18650 #endif
18651 #elif defined(HAVE_LOCALTIME_R)
18652  if (localtime_r(&n, pT) != SOAP_FUNC_R_ERR)
18653  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
18654 #else
18655  pT = localtime(&n);
18656  if (pT)
18657  l = strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
18658 #endif
18659  if (!l)
18660  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), "1969-12-31T23:59:59Z");
18661  return soap->tmpbuf;
18662 }
18663 #endif
18664 
18665 /******************************************************************************/
18666 
18667 #ifndef WITH_LEAN
18668 SOAP_FMAC1
18669 int
18670 SOAP_FMAC2
18671 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
18672 {
18673  if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
18675  return soap->error;
18676  return soap_element_end_out(soap, tag);
18677 }
18678 #endif
18679 
18680 /******************************************************************************/
18681 
18682 #ifndef WITH_LEAN
18683 SOAP_FMAC1
18684 int
18685 SOAP_FMAC2
18686 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
18687 {
18688  *p = 0;
18689  if (s)
18690  {
18691  char *t;
18692  unsigned long d;
18693  struct tm T;
18694  if (!*s)
18695  return soap->error = SOAP_EMPTY;
18696  memset((void*)&T, 0, sizeof(T));
18697  d = soap_strtoul(s, &t, 10);
18698  if (*t == '-')
18699  {
18700  /* YYYY-MM-DD */
18701  T.tm_year = (int)d;
18702  T.tm_mon = (int)soap_strtoul(t + 1, &t, 10);
18703  T.tm_mday = (int)soap_strtoul(t + 1, &t, 10);
18704  }
18705  else if (!(soap->mode & SOAP_XML_STRICT))
18706  {
18707  /* YYYYMMDD */
18708  T.tm_year = (int)(d / 10000);
18709  T.tm_mon = (int)(d / 100 % 100);
18710  T.tm_mday = (int)(d % 100);
18711  }
18712  else
18713  {
18714  return soap->error = SOAP_TYPE;
18715  }
18716  if (*t == 'T' || ((*t == 't' || *t == ' ') && !(soap->mode & SOAP_XML_STRICT)))
18717  {
18718  d = soap_strtoul(t + 1, &t, 10);
18719  if (*t == ':')
18720  {
18721  /* Thh:mm:ss */
18722  T.tm_hour = (int)d;
18723  T.tm_min = (int)soap_strtoul(t + 1, &t, 10);
18724  T.tm_sec = (int)soap_strtoul(t + 1, &t, 10);
18725  }
18726  else if (!(soap->mode & SOAP_XML_STRICT))
18727  {
18728  /* Thhmmss */
18729  T.tm_hour = (int)(d / 10000);
18730  T.tm_min = (int)(d / 100 % 100);
18731  T.tm_sec = (int)(d % 100);
18732  }
18733  else
18734  {
18735  return soap->error = SOAP_TYPE;
18736  }
18737  }
18738  if (T.tm_year == 1)
18739  T.tm_year = 70;
18740  else
18741  T.tm_year -= 1900;
18742  T.tm_mon--;
18743  if (*t == '.')
18744  {
18745  for (t++; *t; t++)
18746  if (*t < '0' || *t > '9')
18747  break;
18748  }
18749  if (*t == ' ' && !(soap->mode & SOAP_XML_STRICT))
18750  t++;
18751  if (*t)
18752  {
18753 #ifndef WITH_NOZONE
18754  if (*t == '+' || *t == '-')
18755  {
18756  int h, m;
18757  m = (int)soap_strtol(t, &t, 10);
18758  if (*t == ':')
18759  {
18760  /* +hh:mm */
18761  h = m;
18762  m = (int)soap_strtol(t + 1, &t, 10);
18763  if (h < 0)
18764  m = -m;
18765  }
18766  else if (!(soap->mode & SOAP_XML_STRICT))
18767  {
18768  /* +hhmm */
18769  h = m / 100;
18770  m = m % 100;
18771  }
18772  else
18773  {
18774  /* +hh */
18775  h = m;
18776  m = 0;
18777  }
18778  if (*t)
18779  return soap->error = SOAP_TYPE;
18780  T.tm_min -= m;
18781  T.tm_hour -= h;
18782  /* put hour and min in range */
18783  T.tm_hour += T.tm_min / 60;
18784  T.tm_min %= 60;
18785  if (T.tm_min < 0)
18786  {
18787  T.tm_min += 60;
18788  T.tm_hour--;
18789  }
18790  T.tm_mday += T.tm_hour / 24;
18791  T.tm_hour %= 24;
18792  if (T.tm_hour < 0)
18793  {
18794  T.tm_hour += 24;
18795  T.tm_mday--;
18796  }
18797  /* note: day of the month may be out of range, timegm() handles it */
18798  }
18799  else if (*t != 'Z')
18800  {
18801  return soap->error = SOAP_TYPE;
18802  }
18803 #endif
18804  *p = soap_timegm(&T);
18805  }
18806  else /* no UTC or timezone, so assume we got a localtime */
18807  {
18808  T.tm_isdst = -1;
18809  *p = mktime(&T);
18810  }
18811  }
18812  return soap->error;
18813 }
18814 #endif
18815 
18816 /******************************************************************************/
18817 
18818 #ifndef WITH_LEAN
18819 SOAP_FMAC1
18820 time_t *
18821 SOAP_FMAC2
18822 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
18823 {
18824  if (soap_element_begin_in(soap, tag, 0, NULL))
18825  return NULL;
18826  if (*soap->type
18828  && soap_match_tag(soap, soap->type, ":dateTime"))
18829  {
18830  soap->error = SOAP_TYPE;
18831  soap_revert(soap);
18832  return NULL;
18833  }
18834  p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), NULL, NULL, NULL, NULL);
18835  if (!p)
18836  return NULL;
18837  if (*soap->href != '#')
18838  {
18839  int err = soap_s2dateTime(soap, soap_value(soap), p);
18840  if ((soap->body && soap_element_end_in(soap, tag)) || err)
18841  return NULL;
18842  }
18843  else
18844  {
18845  p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, t, sizeof(time_t), 0, NULL, NULL);
18846  if (soap->body && soap_element_end_in(soap, tag))
18847  return NULL;
18848  }
18849  return p;
18850 }
18851 #endif
18852 
18853 /******************************************************************************/
18854 
18855 SOAP_FMAC1
18856 int
18857 SOAP_FMAC2
18858 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
18859 {
18860  if (tag && *tag != '-')
18861  if (soap_element_begin_out(soap, tag, 0, type))
18862  return soap->error;
18863  if (p && *p)
18864  if (soap_send(soap, *p)) /* send as-is */
18865  return soap->error;
18866  if (tag && *tag != '-')
18867  return soap_element_end_out(soap, tag);
18868  return SOAP_OK;
18869 }
18870 
18871 /******************************************************************************/
18872 
18873 SOAP_FMAC1
18874 char **
18875 SOAP_FMAC2
18876 soap_inliteral(struct soap *soap, const char *tag, char **p)
18877 {
18878  if (soap_element_begin_in(soap, tag, 1, NULL))
18879  {
18880  if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT)
18881  return NULL;
18882  soap->error = SOAP_OK;
18883  }
18884  if (!p)
18885  {
18886  p = (char**)soap_malloc(soap, sizeof(char*));
18887  if (!p)
18888  return NULL;
18889  }
18890  if (soap->body || (tag && *tag == '-'))
18891  {
18892  if (tag && *tag != '-')
18893  *p = soap_string_in(soap, -1, -1, -1, NULL);
18894  else
18895  *p = soap_string_in(soap, 0, -1, -1, NULL);
18896  if (!*p)
18897  return NULL;
18898  if (!**p && tag && *tag == '-')
18899  {
18900  soap->error = SOAP_NO_TAG;
18901  return NULL;
18902  }
18903  }
18904  else if (soap->null)
18905  {
18906  *p = NULL;
18907  }
18908  else
18909  {
18910  *p = soap_strdup(soap, SOAP_STR_EOS);
18911  }
18912  if (soap->body && soap_element_end_in(soap, tag))
18913  return NULL;
18914  return p;
18915 }
18916 
18917 /******************************************************************************/
18918 
18919 #ifndef WITH_LEANER
18920 SOAP_FMAC1
18921 int
18922 SOAP_FMAC2
18923 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
18924 {
18925  if (tag && *tag != '-')
18926  if (soap_element_begin_out(soap, tag, 0, type))
18927  return soap->error;
18928  if (p)
18929  {
18930  wchar_t c;
18931  const wchar_t *s = *p;
18932  while ((c = *s++))
18933  {
18934  if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */
18935  return soap->error;
18936  }
18937  }
18938  if (tag && *tag != '-')
18939  return soap_element_end_out(soap, tag);
18940  return SOAP_OK;
18941 }
18942 #endif
18943 
18944 /******************************************************************************/
18945 
18946 #ifndef WITH_LEANER
18947 SOAP_FMAC1
18948 wchar_t **
18949 SOAP_FMAC2
18950 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
18951 {
18952  if (soap_element_begin_in(soap, tag, 1, NULL))
18953  {
18954  if (soap->error != SOAP_NO_TAG || soap_peek(soap) == SOAP_TT)
18955  return NULL;
18956  soap->error = SOAP_OK;
18957  }
18958  if (!p)
18959  {
18960  p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*));
18961  if (!p)
18962  return NULL;
18963  }
18964  if (soap->body)
18965  {
18966  if (tag && *tag != '-')
18967  *p = soap_wstring_in(soap, -1, -1, -1, NULL);
18968  else
18969  *p = soap_wstring_in(soap, 0, -1, -1, NULL);
18970  if (!*p)
18971  return NULL;
18972  if (!**p && tag && *tag == '-')
18973  {
18974  soap->error = SOAP_NO_TAG;
18975  return NULL;
18976  }
18977  }
18978  else if (tag && *tag == '-')
18979  {
18980  soap->error = SOAP_NO_TAG;
18981  return NULL;
18982  }
18983  else if (soap->null)
18984  {
18985  *p = NULL;
18986  }
18987  else
18988  {
18989  *p = soap_wstrdup(soap, L"");
18990  }
18991  if (soap->body && soap_element_end_in(soap, tag))
18992  return NULL;
18993  return p;
18994 }
18995 #endif
18996 
18997 /******************************************************************************/
18998 
18999 SOAP_FMAC1
19000 const char *
19001 SOAP_FMAC2
19003 {
19004  size_t i;
19005  soap_wchar c = 0;
19006  char *s = soap->tmpbuf;
19007  if (!soap->body)
19008  return SOAP_STR_EOS;
19009  do
19010  {
19011  c = soap_get(soap);
19012  } while (soap_coblank(c));
19013  for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
19014  {
19015  if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
19016  break;
19017  *s++ = (char)c;
19018  c = soap_get(soap);
19019  }
19020  for (s--; i > 0; i--, s--)
19021  {
19022  if (!soap_coblank((soap_wchar)*s))
19023  break;
19024  }
19025  s[1] = '\0';
19026  soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */
19027  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
19028  if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
19029  {
19030  soap_unget(soap, c);
19031  }
19032  else
19033  {
19034  soap->error = SOAP_LENGTH;
19035  return NULL;
19036  }
19037 #ifdef WITH_DOM
19038  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
19039  {
19041  if (!soap->dom->text)
19042  return NULL;
19043  }
19044 #endif
19045  return soap->tmpbuf; /* return non-null pointer */
19046 }
19047 
19048 /******************************************************************************/
19049 
19050 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
19051 SOAP_FMAC1
19052 int
19053 SOAP_FMAC2
19054 soap_getline(struct soap *soap, char *buf, int len)
19055 {
19056  char *s = buf;
19057  int i = len;
19058  soap_wchar c = 0;
19059  for (;;)
19060  {
19061  while (i > 1)
19062  {
19063  c = soap_getchar(soap);
19064  if (c == '\r' || c == '\n')
19065  break;
19066  if ((int)c == EOF)
19067  return soap->error = SOAP_CHK_EOF;
19068  *s++ = (char)c;
19069  i--;
19070  }
19071  *s = '\0';
19072  if (c != '\n')
19073  c = soap_getchar(soap); /* got \r or something else, now get \n */
19074  if (c == '\n')
19075  {
19076  if (i == len) /* empty line: end of HTTP/MIME header */
19077  break;
19078  c = soap_get0(soap);
19079  if (c != ' ' && c != '\t') /* HTTP line continuation? */
19080  break;
19081  }
19082  else if ((int)c == EOF)
19083  {
19084  return soap->error = SOAP_CHK_EOF;
19085  }
19086  else if (i <= 1)
19087  {
19088  return soap->error = SOAP_HDR;
19089  }
19090  }
19091  return SOAP_OK;
19092 }
19093 #endif
19094 
19095 /******************************************************************************/
19096 
19097 static ULONG64
19099 {
19100 #ifndef WITH_LEANER
19101  struct soap_multipart *content;
19102  ULONG64 count = soap->count;
19103  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=" SOAP_ULONG_FORMAT "\n", count));
19104  if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
19105  {
19106  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
19107  for (content = soap->dime.first; content; content = content->next)
19108  {
19109  count += 12 + ((content->size+3)&(~3));
19110  if (content->id)
19111  count += ((strlen(content->id)+3)&(~3));
19112  if (content->type)
19113  count += ((strlen(content->type)+3)&(~3));
19114  if (content->options)
19115  count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
19116  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
19117  }
19118  }
19119  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
19120  {
19121  size_t n = strlen(soap->mime.boundary);
19122  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
19123  for (content = soap->mime.first; content; content = content->next)
19124  {
19125  const char *s;
19126  /* count \r\n--boundary\r\n */
19127  count += 6 + n;
19128  /* count Content-Type: ...\r\n */
19129  if (content->type)
19130  count += 16 + strlen(content->type);
19131  /* count Content-Transfer-Encoding: ...\r\n */
19132  s = soap_code_str(mime_codes, content->encoding);
19133  if (s)
19134  count += 29 + strlen(s);
19135  /* count Content-ID: ...\r\n */
19136  if (content->id)
19137  count += 14 + strlen(content->id);
19138  /* count Content-Location: ...\r\n */
19139  if (content->location)
19140  count += 20 + strlen(content->location);
19141  /* count Content-Description: ...\r\n */
19142  if (content->description)
19143  count += 23 + strlen(content->description);
19144  /* count \r\n...content */
19145  count += 2 + content->size;
19146  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
19147  }
19148  /* count \r\n--boundary-- */
19149  count += 6 + n;
19150  }
19151  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=" SOAP_ULONG_FORMAT "\n", count));
19152  return count;
19153 #else
19154  return soap->count;
19155 #endif
19156 }
19157 
19158 /******************************************************************************/
19159 
19160 #ifndef WITH_LEANER
19161 static int
19162 soap_putdimefield(struct soap *soap, const char *s, size_t n)
19163 {
19164  if (soap_send_raw(soap, s, n))
19165  return soap->error;
19166  return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
19167 }
19168 #endif
19169 
19170 /******************************************************************************/
19171 
19172 #ifndef WITH_LEANER
19173 SOAP_FMAC1
19174 char *
19175 SOAP_FMAC2
19176 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
19177 {
19178  size_t n;
19179  char *s = NULL;
19180  if (option)
19181  {
19182  n = strlen(option);
19183  s = (char*)soap_malloc(soap, n + 5);
19184  if (s)
19185  {
19186  s[0] = (char)(optype >> 8);
19187  s[1] = (char)(optype & 0xFF);
19188  s[2] = (char)(n >> 8);
19189  s[3] = (char)(n & 0xFF);
19190  soap_strcpy(s + 4, n + 1, option);
19191  }
19192  }
19193  return s;
19194 }
19195 #endif
19196 
19197 /******************************************************************************/
19198 
19199 #ifndef WITH_LEANER
19200 SOAP_FMAC1
19201 int
19202 SOAP_FMAC2
19204 {
19205  unsigned char tmp[12];
19206  size_t optlen = 0, idlen = 0, typelen = 0;
19207  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS));
19208  if (soap->dime.options)
19209  optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
19210  if (soap->dime.id)
19211  {
19212  idlen = strlen(soap->dime.id);
19213  if (idlen > 0x0000FFFF)
19214  idlen = 0x0000FFFF;
19215  }
19216  if (soap->dime.type)
19217  {
19218  typelen = strlen(soap->dime.type);
19219  if (typelen > 0x0000FFFF)
19220  typelen = 0x0000FFFF;
19221  }
19222  tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
19223  tmp[1] = soap->dime.flags & 0xF0;
19224  tmp[2] = (char)(optlen >> 8);
19225  tmp[3] = (char)(optlen & 0xFF);
19226  tmp[4] = (char)(idlen >> 8);
19227  tmp[5] = (char)(idlen & 0xFF);
19228  tmp[6] = (char)(typelen >> 8);
19229  tmp[7] = (char)(typelen & 0xFF);
19230  tmp[8] = (char)(soap->dime.size >> 24);
19231  tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
19232  tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
19233  tmp[11] = (char)(soap->dime.size & 0xFF);
19234  if (soap_send_raw(soap, (char*)tmp, 12)
19235  || soap_putdimefield(soap, soap->dime.options, optlen)
19236  || soap_putdimefield(soap, soap->dime.id, idlen)
19237  || soap_putdimefield(soap, soap->dime.type, typelen))
19238  return soap->error;
19239  return SOAP_OK;
19240 }
19241 #endif
19242 
19243 /******************************************************************************/
19244 
19245 #ifndef WITH_LEANER
19246 SOAP_FMAC1
19247 int
19248 SOAP_FMAC2
19250 {
19251  struct soap_multipart *content;
19252  if (!(soap->mode & SOAP_ENC_DIME))
19253  return SOAP_OK;
19254  for (content = soap->dime.first; content; content = content->next)
19255  {
19256  void *handle;
19257  soap->dime.size = content->size;
19258  soap->dime.id = content->id;
19259  soap->dime.type = content->type;
19260  soap->dime.options = content->options;
19262  if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) != NULL || soap->error))
19263  {
19264  size_t size = content->size;
19265  if (!handle)
19266  {
19267  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
19268  return soap->error;
19269  }
19270  if (!size && ((soap->mode & SOAP_ENC_PLAIN) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
19271  {
19272  size_t chunksize = sizeof(soap->tmpbuf);
19273  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
19274  do
19275  {
19276  size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
19277  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
19278  if (size < chunksize)
19279  {
19280  soap->dime.flags &= ~SOAP_DIME_CF;
19281  if (!content->next)
19283  }
19284  else
19285  {
19287  }
19288  soap->dime.size = size;
19289  if (soap_putdimehdr(soap)
19291  break;
19292  if (soap->dime.id)
19293  {
19295  soap->dime.id = NULL;
19296  soap->dime.type = NULL;
19297  soap->dime.options = NULL;
19298  }
19299  } while (size >= chunksize);
19300  }
19301  else
19302  {
19303  if (!content->next)
19305  if (soap_putdimehdr(soap))
19306  return soap->error;
19307  do
19308  {
19309  size_t bufsize;
19310  if (size < sizeof(soap->tmpbuf))
19311  bufsize = size;
19312  else
19313  bufsize = sizeof(soap->tmpbuf);
19314  bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize);
19315  if (!bufsize)
19316  {
19317  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
19318  soap->error = SOAP_CHK_EOF;
19319  break;
19320  }
19321  if (soap_send_raw(soap, soap->tmpbuf, bufsize))
19322  break;
19323  size -= bufsize;
19324  } while (size);
19325  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
19326  if (soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3))
19327  return soap->error;
19328  }
19329  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
19330  if (soap->fdimereadclose)
19331  soap->fdimereadclose(soap, handle);
19332  }
19333  else
19334  {
19335  if (!content->next)
19337  if (soap_putdimehdr(soap)
19338  || soap_putdimefield(soap, (char*)content->ptr, content->size))
19339  return soap->error;
19340  }
19341  }
19342  return SOAP_OK;
19343 }
19344 #endif
19345 
19346 /******************************************************************************/
19347 
19348 #ifndef WITH_LEANER
19349 static char *
19350 soap_getdimefield(struct soap *soap, size_t n)
19351 {
19352  char *p = NULL;
19353  if (n > 0)
19354  {
19355  p = (char*)soap_malloc(soap, n + 1 > n ? n + 1 : n);
19356  if (p)
19357  {
19358  char *s = p;
19359  size_t i;
19360  for (i = n; i > 0; i--)
19361  {
19363  if ((int)c == EOF)
19364  {
19365  soap->error = SOAP_CHK_EOF;
19366  return NULL;
19367  }
19368  *s++ = (char)c;
19369  }
19370  if (n + 1 > n)
19371  *s = '\0'; /* force NUL terminated */
19372  soap->error = soap_move(soap, (size_t)(-(long)n&3));
19373  if (soap->error)
19374  return NULL;
19375  }
19376  else
19377  {
19378  soap->error = SOAP_EOM;
19379  }
19380  }
19381  return p;
19382 }
19383 #endif
19384 
19385 /******************************************************************************/
19386 
19387 #ifndef WITH_LEANER
19388 SOAP_FMAC1
19389 int
19390 SOAP_FMAC2
19392 {
19393  soap_wchar c;
19394  char *s;
19395  int i;
19396  unsigned char tmp[12];
19397  size_t optlen, idlen, typelen;
19398  if (!(soap->mode & SOAP_ENC_DIME))
19399  return soap->error = SOAP_DIME_END;
19400  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
19401  s = (char*)tmp;
19402  for (i = 12; i > 0; i--)
19403  {
19404  c = soap_getchar(soap);
19405  if ((int)c == EOF)
19406  return soap->error = SOAP_CHK_EOF;
19407  *s++ = (char)c;
19408  }
19409  if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
19410  return soap->error = SOAP_DIME_MISMATCH;
19411  soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
19412  optlen = (tmp[2] << 8) | tmp[3];
19413  idlen = (tmp[4] << 8) | tmp[5];
19414  typelen = (tmp[6] << 8) | tmp[7];
19415  soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
19416  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
19417  soap->dime.options = soap_getdimefield(soap, optlen);
19418  if (!soap->dime.options && soap->error)
19419  return soap->error;
19420  soap->dime.id = soap_getdimefield(soap, idlen);
19421  if (!soap->dime.id && soap->error)
19422  return soap->error;
19423  soap->dime.type = soap_getdimefield(soap, typelen);
19424  if (!soap->dime.type && soap->error)
19425  return soap->error;
19426  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME flags=%x id='%s', type='%s', options='%s'\n", soap->dime.flags, soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "", soap->dime.options ? soap->dime.options+4 : SOAP_STR_EOS));
19427  if ((soap->dime.flags & SOAP_DIME_ME))
19428  soap->mode &= ~SOAP_ENC_DIME;
19429  return SOAP_OK;
19430 }
19431 #endif
19432 
19433 /******************************************************************************/
19434 
19435 #ifndef WITH_LEANER
19436 SOAP_FMAC1
19437 int
19438 SOAP_FMAC2
19440 {
19441  if (soap->dime.buflen || soap->dime.chunksize)
19442  {
19443  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip remainder of SOAP in DIME (%u bytes or %u bytes in chunk left)\n", (unsigned int)soap->dime.buflen, (unsigned int)soap->dime.chunksize));
19444  do
19445  if (soap_get1(soap) == (int)EOF)
19446  return soap->error = SOAP_CHK_EOF;
19447  while (soap->dime.buflen || soap->dime.chunksize);
19448  if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
19449  return soap->error = SOAP_CHK_EOF;
19450  if (!(soap->mode & SOAP_ENC_DIME))
19451  return SOAP_OK;
19452  }
19453  else
19454  {
19455  if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap))))
19456  return soap->error = SOAP_CHK_EOF;
19457  }
19458  for (;;)
19459  {
19460  struct soap_multipart *content;
19461  if (soap_getdimehdr(soap))
19462  break;
19464  {
19465  const char *id, *type, *options;
19466  size_t size, n;
19467  if (!soap->dime.ptr)
19468  return soap->error;
19469  id = soap->dime.id;
19470  type = soap->dime.type;
19471  options = soap->dime.options;
19472  for (;;)
19473  {
19474  size = soap->dime.size;
19475  for (;;)
19476  {
19477  n = soap->buflen - soap->bufidx;
19478  if (size < n)
19479  n = size;
19480  soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n);
19481  if (soap->error)
19482  break;
19483  size -= n;
19484  if (!size)
19485  {
19486  soap->bufidx += n;
19487  break;
19488  }
19489  if (soap_recv(soap))
19490  {
19491  soap->error = SOAP_EOF;
19492  goto end;
19493  }
19494  }
19495  if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
19496  {
19497  soap->error = SOAP_EOF;
19498  break;
19499  }
19500  if (!(soap->dime.flags & SOAP_DIME_CF))
19501  break;
19502  if (soap_getdimehdr(soap))
19503  break;
19504  }
19505 end:
19506  if (soap->fdimewriteclose)
19507  soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
19508  soap->dime.size = 0;
19509  soap->dime.id = id;
19510  soap->dime.type = type;
19511  soap->dime.options = options;
19512  }
19513  else if ((soap->dime.flags & SOAP_DIME_CF))
19514  {
19515  const char *id, *type, *options;
19516  id = soap->dime.id;
19517  type = soap->dime.type;
19518  options = soap->dime.options;
19519  if (soap_alloc_block(soap) == NULL)
19520  return soap->error = SOAP_EOM;
19521  for (;;)
19522  {
19523  soap_wchar c;
19524  size_t i;
19525  char *s;
19526  if (soap->dime.size > SOAP_MAXDIMESIZE)
19527  {
19528  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE));
19529  return soap->error = SOAP_DIME_ERROR;
19530  }
19531  s = (char*)soap_push_block(soap, NULL, soap->dime.size);
19532  if (!s)
19533  return soap->error = SOAP_EOM;
19534  for (i = soap->dime.size; i > 0; i--)
19535  {
19536  c = soap_get1(soap);
19537  if ((int)c == EOF)
19538  return soap->error = SOAP_EOF;
19539  *s++ = (char)c;
19540  }
19541  if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
19542  return soap->error = SOAP_EOF;
19543  if (!(soap->dime.flags & SOAP_DIME_CF))
19544  break;
19545  if (soap_getdimehdr(soap))
19546  return soap->error;
19547  }
19548  soap->dime.size = soap->blist->size;
19549  if (soap->dime.size + 1 > soap->dime.size)
19550  soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */
19552  if (!soap->dime.ptr)
19553  return soap->error;
19554  if (soap->dime.size + 1 > soap->dime.size)
19555  soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated, just in case even though this is binary data */
19556  soap->dime.id = id;
19557  soap->dime.type = type;
19558  soap->dime.options = options;
19559  }
19560  else
19561  {
19563  }
19565  if (!content)
19566  return soap->error = SOAP_EOM;
19567  content->id = soap->dime.id;
19568  content->type = soap->dime.type;
19569  content->options = soap->dime.options;
19570  if (soap->error)
19571  return soap->error;
19572  soap_resolve_attachment(soap, content);
19573  }
19574  if (soap->error != SOAP_DIME_END)
19575  return soap->error;
19576  return soap->error = SOAP_OK;
19577 }
19578 #endif
19579 
19580 /******************************************************************************/
19581 
19582 #ifndef WITH_LEANER
19583 SOAP_FMAC1
19584 int
19585 SOAP_FMAC2
19587 {
19588  struct soap_multipart *content;
19589  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME header\n"));
19590  do
19591  {
19592  if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
19593  return soap->error;
19594  } while (!*soap->msgbuf);
19595  if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
19596  {
19597  char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
19598  /* remove white space */
19599  while (soap_coblank((soap_wchar)*s))
19600  s--;
19601  s[1] = '\0';
19602  if (soap->mime.boundary)
19603  {
19604  if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
19605  return soap->error = SOAP_MIME_ERROR;
19606  }
19607  else
19608  {
19610  if (!soap->mime.boundary)
19611  return soap->error = SOAP_EOM;
19612  }
19613  if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
19614  return soap->error;
19615  }
19617  return soap->error = SOAP_EOM;
19618  content = soap->mime.last;
19619  for (;;)
19620  {
19621  char *key = soap->msgbuf;
19622  char *val;
19623  if (!*key)
19624  break;
19625  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
19626  val = strchr(soap->msgbuf, ':');
19627  if (val)
19628  {
19629  *val = '\0';
19630  do
19631  {
19632  val++;
19633  } while (*val && *val <= 32);
19634  if (!soap_tag_cmp(key, "Content-ID"))
19635  content->id = soap_strdup(soap, val);
19636  else if (!soap_tag_cmp(key, "Content-Location"))
19637  content->location = soap_strdup(soap, val);
19638  else if (!content->id && !soap_tag_cmp(key, "Content-Disposition"))
19639  content->id = soap_strdup(soap, soap_http_header_attribute(soap, val, "name"));
19640  else if (!soap_tag_cmp(key, "Content-Type"))
19641  content->type = soap_strdup(soap, val);
19642  else if (!soap_tag_cmp(key, "Content-Description"))
19643  content->description = soap_strdup(soap, val);
19644  else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
19646  }
19647  if (soap_getline(soap, key, sizeof(soap->msgbuf)))
19648  return soap->error;
19649  }
19650  return SOAP_OK;
19651 }
19652 #endif
19653 
19654 /******************************************************************************/
19655 
19656 #ifndef WITH_LEANER
19657 SOAP_FMAC1
19658 int
19659 SOAP_FMAC2
19661 {
19663  continue;
19664  return soap->error;
19665 }
19666 #endif
19667 
19668 /******************************************************************************/
19669 
19670 #ifndef WITH_LEANER
19671 SOAP_FMAC1
19672 void
19673 SOAP_FMAC2
19675 {
19677 }
19678 #endif
19679 
19680 /******************************************************************************/
19681 
19682 #ifndef WITH_LEANER
19683 SOAP_FMAC1
19684 int
19685 SOAP_FMAC2
19687 {
19688  if ((soap->mode & SOAP_MIME_POSTCHECK))
19690  return 0;
19691 }
19692 #endif
19693 
19694 /******************************************************************************/
19695 
19696 #ifndef WITH_LEANER
19697 SOAP_FMAC1
19698 struct soap_multipart *
19699 SOAP_FMAC2
19700 soap_recv_mime_attachment(struct soap *soap, void *handle)
19701 {
19702  soap_wchar c = 0;
19703  size_t i, m = 0;
19704  char *s, *t = NULL;
19705  struct soap_multipart *content;
19706  short flag = 0;
19707  if (!(soap->mode & SOAP_ENC_MIME))
19708  goto post_check_exit;
19709  content = soap->mime.last;
19710  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get MIME (%p)\n", (void*)content));
19711  if (!content)
19712  {
19713  if (soap_getmimehdr(soap))
19714  goto post_check_exit;
19715  content = soap->mime.last;
19716  }
19717  else if (content != soap->mime.first)
19718  {
19719  if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) != NULL || soap->error))
19720  {
19721  if (!content->ptr)
19722  goto post_check_exit;
19723  }
19724  }
19725  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id='%s' type='%s'\n", content->id ? content->id : SOAP_STR_EOS, content->type ? content->type : SOAP_STR_EOS));
19726  if (!content->ptr && soap_alloc_block(soap) == NULL)
19727  {
19728  soap->error = SOAP_EOM;
19729  goto post_check_exit;
19730  }
19731  for (;;)
19732  {
19733  if (content->ptr)
19734  {
19735  s = soap->tmpbuf;
19736  }
19737  else
19738  {
19739  s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf));
19740  if (!s)
19741  {
19742  soap->error = SOAP_EOM;
19743  goto post_check_exit;
19744  }
19745  }
19746  for (i = 0; i < sizeof(soap->tmpbuf); i++)
19747  {
19748  if (m > 0)
19749  {
19750  *s++ = *t++;
19751  m--;
19752  }
19753  else
19754  {
19755  if (!flag)
19756  {
19757  c = soap_getchar(soap);
19758  if ((int)c == EOF)
19759  {
19760  if (content->ptr && soap->fmimewriteclose)
19761  soap->fmimewriteclose(soap, (void*)content->ptr);
19762  soap->error = SOAP_CHK_EOF;
19763  goto post_check_exit;
19764  }
19765  }
19766  if (flag || c == '\r')
19767  {
19768  memset((void*)soap->msgbuf, 0, sizeof(soap->msgbuf));
19769  soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "\n--");
19770  if (soap->mime.boundary)
19771  {
19772  if (soap_strncat(soap->msgbuf, sizeof(soap->msgbuf), soap->mime.boundary, sizeof(soap->msgbuf) - 4))
19773  {
19775  goto post_check_exit;
19776  }
19777  }
19778  t = soap->msgbuf;
19779  do
19780  {
19781  c = soap_getchar(soap);
19782  } while (c == *t++);
19783  if ((int)c == EOF)
19784  {
19785  if (content->ptr && soap->fmimewriteclose)
19786  soap->fmimewriteclose(soap, (void*)content->ptr);
19787  soap->error = SOAP_CHK_EOF;
19788  goto post_check_exit;
19789  }
19790  if (!*--t)
19791  goto end;
19792  *t = (char)c;
19793  flag = (c == '\r');
19794  m = t - soap->msgbuf + 1 - flag;
19795  t = soap->msgbuf;
19796  c = '\r';
19797  }
19798  *s++ = (char)c;
19799  }
19800  }
19801  if (content->ptr && soap->fmimewrite)
19802  {
19803  soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
19804  if (soap->error)
19805  break;
19806  }
19807  }
19808 end:
19809  if (content->ptr)
19810  {
19811  if (!soap->error && soap->fmimewrite)
19812  soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
19813  if (soap->fmimewriteclose)
19814  soap->fmimewriteclose(soap, (void*)content->ptr);
19815  if (soap->error)
19816  goto post_check_exit;
19817  }
19818  else
19819  {
19820  *s = '\0'; /* make 0-terminated, just in case even though this is binary data */
19821  content->size = soap_size_block(soap, NULL, i + 1) - 1; /* last block with '\0' */
19822  content->ptr = soap_save_block(soap, NULL, NULL, 0);
19823  }
19824  soap_resolve_attachment(soap, content);
19825  if (c == '-' && soap_getchar(soap) == '-')
19826  {
19827  soap->mode &= ~SOAP_ENC_MIME;
19828  if ((soap->mode & SOAP_MIME_POSTCHECK))
19829  {
19830  if (soap_end_recv(soap))
19831  goto post_check_exit;
19832  if (soap->keep_alive == -2) /* special case to keep alive */
19833  soap->keep_alive = 0;
19835  }
19836  }
19837  else
19838  {
19839  while (c != '\r' && (int)c != EOF && soap_coblank(c))
19840  c = soap_getchar(soap);
19841  if (c != '\r' || soap_getchar(soap) != '\n')
19842  {
19844  goto post_check_exit;
19845  }
19846  if (soap_getmimehdr(soap))
19847  goto post_check_exit;
19848  }
19849  return content;
19850 post_check_exit:
19851  if ((soap->mode & SOAP_MIME_POSTCHECK))
19852  {
19853  if (soap->keep_alive == -2) /* special case to keep alive */
19854  soap->keep_alive = 0;
19856  }
19857  return NULL;
19858 }
19859 #endif
19860 
19861 /******************************************************************************/
19862 
19863 #ifndef WITH_LEANER
19864 SOAP_FMAC1
19865 int
19866 SOAP_FMAC2
19867 soap_match_cid(struct soap *soap, const char *s, const char *t)
19868 {
19869  size_t n;
19870  if (!s)
19871  return 1;
19872  if (!strcmp(s, t))
19873  return 0;
19874  if (!strncmp(s, "cid:", 4))
19875  s += 4;
19876  n = strlen(t);
19877  if (*t == '<')
19878  {
19879  t++;
19880  n -= 2;
19881  }
19882  if (!strncmp(s, t, n) && !s[n])
19883  return 0;
19884  (void)soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
19885  if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
19886  return 0;
19887  return 1;
19888 }
19889 #endif
19890 
19891 /******************************************************************************/
19892 
19893 /* return UUID "<prefix>xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx" in a temporary buffer */
19894 SOAP_FMAC1
19895 const char*
19896 SOAP_FMAC2
19897 soap_rand_uuid(struct soap *soap, const char *prefix)
19898 {
19899  int r1, r2, r3, r4;
19900 #ifdef WITH_OPENSSL
19901  r1 = soap_random;
19902  r2 = soap_random;
19903 #else
19904  size_t i;
19905  static int k = 0xFACEB00C;
19906  int lo = k % 127773;
19907  int hi = k / 127773;
19908 # if defined(HAVE_GETTIMEOFDAY)
19909  struct timeval tv;
19910  gettimeofday(&tv, NULL);
19911  r1 = 10000000 * tv.tv_sec + tv.tv_usec;
19912 # elif defined(UNDER_CE)
19913  r1 = (int)Random();
19914 # elif !defined(WITH_LEAN)
19915  r1 = (int)time(NULL);
19916 # else
19917  r1 = k;
19918 # endif
19919  k = 16807 * lo - 2836 * hi;
19920  if (k <= 0)
19921  k += 0x7FFFFFFF;
19922  r2 = k;
19923  /* k &= 0x8FFFFFFF; */
19924  for (i = 0; i < (sizeof(soap->buf) < 16UL ? sizeof(soap->buf) : 16UL); i++)
19925  r2 += soap->buf[i];
19926 #endif
19927  r3 = soap_random;
19928  r4 = soap_random;
19929  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), prefix ? strlen(prefix) + 37 : 37), "%s%8.8x-%4.4hx-4%3.3hx-%4.4hx-%4.4hx%8.8x", prefix ? prefix : SOAP_STR_EOS, r1, (short)(r2 >> 16), (short)(((short)r2 >> 4) & 0x0FFF), (short)(((short)(r3 >> 16) & 0x3FFF) | 0x8000), (short)r3, r4);
19930  return soap->tmpbuf;
19931 }
19932 
19933 /******************************************************************************/
19934 
19935 #ifndef WITH_LEANER
19936 static void
19938 {
19939  if (content->id)
19940  {
19941  struct soap_xlist **xp = &soap->xlist;
19942  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id));
19943  while (*xp)
19944  {
19945  struct soap_xlist *xq = *xp;
19946  if (!soap_match_cid(soap, xq->id, content->id))
19947  {
19948  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id));
19949  *xp = xq->next;
19950  *xq->ptr = (unsigned char*)content->ptr;
19951  *xq->size = (int)content->size;
19952  *xq->type = (char*)content->type;
19953  if (content->options)
19954  *xq->options = (char*)content->options;
19955  else
19956  *xq->options = (char*)content->description;
19957  SOAP_FREE(soap, xq);
19958  }
19959  else
19960  {
19961  xp = &(*xp)->next;
19962  }
19963  }
19964  }
19965 }
19966 #endif
19967 
19968 /******************************************************************************/
19969 
19970 #ifndef WITH_LEANER
19971 SOAP_FMAC1
19972 int
19973 SOAP_FMAC2
19974 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
19975 {
19976  const char *s;
19977  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS));
19978  if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
19979  return soap->error;
19980  if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
19981  return soap->error;
19982  s = soap_code_str(mime_codes, content->encoding);
19983  if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
19984  return soap->error;
19985  if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
19986  return soap->error;
19987  if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
19988  return soap->error;
19989  if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
19990  return soap->error;
19991  return soap_send_raw(soap, "\r\n", 2);
19992 }
19993 #endif
19994 
19995 /******************************************************************************/
19996 
19997 #ifndef WITH_LEANER
19998 SOAP_FMAC1
19999 int
20000 SOAP_FMAC2
20002 {
20003  struct soap_multipart *content;
20004  if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
20005  return SOAP_OK;
20006  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
20007  for (content = soap->mime.first; content; content = content->next)
20008  {
20009  void *handle;
20010  if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) != NULL || soap->error))
20011  {
20012  size_t size = content->size;
20013  if (!handle)
20014  {
20015  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
20016  return soap->error;
20017  }
20018  if (soap_putmimehdr(soap, content))
20019  return soap->error;
20020  if (!size)
20021  {
20023  {
20024  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
20025  do
20026  {
20027  size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
20028  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
20029  if (soap_send_raw(soap, soap->tmpbuf, size))
20030  break;
20031  } while (size);
20032  }
20033  else
20034  {
20035  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
20036  }
20037  }
20038  else
20039  {
20040  do
20041  {
20042  size_t bufsize;
20043  if (size < sizeof(soap->tmpbuf))
20044  bufsize = size;
20045  else
20046  bufsize = sizeof(soap->tmpbuf);
20047  bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize);
20048  if (!bufsize)
20049  {
20050  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
20051  soap->error = SOAP_EOF;
20052  break;
20053  }
20054  if (soap_send_raw(soap, soap->tmpbuf, bufsize))
20055  break;
20056  size -= bufsize;
20057  } while (size);
20058  }
20059  if (soap->fmimereadclose)
20060  soap->fmimereadclose(soap, handle);
20061  }
20062  else
20063  {
20064  if (soap_putmimehdr(soap, content)
20065  || soap_send_raw(soap, content->ptr, content->size))
20066  return soap->error;
20067  }
20068  }
20069  return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
20070 }
20071 #endif
20072 
20073 /******************************************************************************/
20074 
20075 #ifndef WITH_LEANER
20076 SOAP_FMAC1
20077 void
20078 SOAP_FMAC2
20080 {
20081  soap->omode |= SOAP_ENC_DIME;
20082  soap->dime.first = NULL;
20083  soap->dime.last = NULL;
20084 }
20085 #endif
20086 
20087 /******************************************************************************/
20088 
20089 #ifndef WITH_LEANER
20090 SOAP_FMAC1
20091 void
20092 SOAP_FMAC2
20093 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
20094 {
20095  soap->omode |= SOAP_ENC_MIME;
20096  soap->mime.first = NULL;
20097  soap->mime.last = NULL;
20098  soap->mime.boundary = soap_strdup(soap, boundary);
20099  soap->mime.start = soap_strdup(soap, start);
20100 }
20101 #endif
20102 
20103 /******************************************************************************/
20104 
20105 #ifndef WITH_LEANER
20106 SOAP_FMAC1
20107 void
20108 SOAP_FMAC2
20110 {
20111  soap->omode &= ~SOAP_ENC_DIME;
20112  soap->dime.first = NULL;
20113  soap->dime.last = NULL;
20114 }
20115 #endif
20116 
20117 /******************************************************************************/
20118 
20119 #ifndef WITH_LEANER
20120 SOAP_FMAC1
20121 void
20122 SOAP_FMAC2
20124 {
20125  soap->omode &= ~SOAP_ENC_MIME;
20126  soap->mime.first = NULL;
20127  soap->mime.last = NULL;
20128  soap->mime.boundary = NULL;
20129  soap->mime.start = NULL;
20130 }
20131 #endif
20132 
20133 /******************************************************************************/
20134 
20135 #ifndef WITH_LEANER
20136 static int
20138 {
20139  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start)
20140  {
20141  const char *s;
20142  if (strlen(soap->mime.boundary) + strlen(soap->mime.start) + 140 > sizeof(soap->tmpbuf))
20143  return soap->error = SOAP_EOM;
20144  if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
20145  {
20146  s = "application/dime";
20147  }
20148  else if (soap->version == 2)
20149  {
20150  if ((soap->mode & SOAP_ENC_MTOM))
20151  s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
20152  else
20153  s = "application/soap+xml; charset=utf-8";
20154  }
20155  else if ((soap->mode & SOAP_ENC_MTOM))
20156  {
20157  s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
20158  }
20159  else
20160  {
20161  s = "text/xml; charset=utf-8";
20162  }
20163  (SOAP_SNPRINTF_SAFE(soap->tmpbuf, sizeof(soap->tmpbuf)), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
20164  if (soap_send(soap, soap->tmpbuf))
20165  return soap->error;
20166  }
20167  if ((soap->mode & SOAP_IO_LENGTH))
20168  soap->dime.size = (size_t)soap->count; /* DIME in MIME correction, soap->count is small */
20169  if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
20170  {
20171  if (soap_putdimehdr(soap))
20172  return soap->error;
20173  }
20174  return SOAP_OK;
20175 }
20176 #endif
20177 
20178 /******************************************************************************/
20179 
20180 #ifndef WITH_LEANER
20181 static int
20183 {
20184  if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
20185  {
20186  if (soap->count > 0xFFFFFFFF)
20187  return soap->error = SOAP_DIME_ERROR;
20188  soap->dime.size = (size_t)soap->count - soap->dime.size; /* DIME in MIME correction */
20189  (SOAP_SNPRINTF(soap->id, sizeof(soap->id), strlen(soap->dime_id_format) + 20), soap->dime_id_format, 0);
20190  soap->dime.id = soap->id;
20192  {
20193  if (soap->local_namespaces[0].out)
20194  soap->dime.type = (char*)soap->local_namespaces[0].out;
20195  else
20196  soap->dime.type = (char*)soap->local_namespaces[0].ns;
20197  }
20198  soap->dime.options = NULL;
20200  if (!soap->dime.first)
20202  soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
20203  }
20204  if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
20205  return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
20206  return SOAP_OK;
20207 }
20208 #endif
20209 
20210 /******************************************************************************/
20211 
20212 #ifndef WITH_LEANER
20213 static struct soap_multipart*
20214 soap_alloc_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, const char *ptr, size_t size)
20215 {
20216  struct soap_multipart *content;
20217  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New DIME/MIME attachment %p (%lu)\n", (void*)ptr, (unsigned long)size));
20218  content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
20219  if (content)
20220  {
20221  content->next = NULL;
20222  content->ptr = ptr;
20223  content->size = size;
20224  content->id = NULL;
20225  content->type = NULL;
20226  content->options = NULL;
20227  content->encoding = SOAP_MIME_NONE;
20228  content->location = NULL;
20229  content->description = NULL;
20230  if (!*first)
20231  *first = content;
20232  if (*last)
20233  (*last)->next = content;
20234  *last = content;
20235  }
20236  return content;
20237 }
20238 #endif
20239 
20240 /******************************************************************************/
20241 
20242 #ifndef WITH_LEANER
20243 SOAP_FMAC1
20244 int
20245 SOAP_FMAC2
20246 soap_set_dime_attachment(struct soap *soap, const char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
20247 {
20249  if (!content)
20250  return SOAP_EOM;
20251  content->id = soap_strdup(soap, id);
20252  content->type = soap_strdup(soap, type);
20253  content->options = soap_dime_option(soap, optype, option);
20254  return SOAP_OK;
20255 }
20256 #endif
20257 
20258 /******************************************************************************/
20259 
20260 #ifndef WITH_LEANER
20261 SOAP_FMAC1
20262 int
20263 SOAP_FMAC2
20264 soap_set_mime_attachment(struct soap *soap, const char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
20265 {
20267  if (!content)
20268  return SOAP_EOM;
20269  content->id = soap_strdup(soap, id);
20270  content->type = soap_strdup(soap, type);
20271  content->encoding = encoding;
20272  content->location = soap_strdup(soap, location);
20273  content->description = soap_strdup(soap, description);
20274  return SOAP_OK;
20275 }
20276 #endif
20277 
20278 /******************************************************************************/
20279 
20280 #ifndef WITH_LEANER
20281 SOAP_FMAC1
20282 struct soap_multipart*
20283 SOAP_FMAC2
20285 {
20286  if (content)
20287  return content->next;
20288  return NULL;
20289 }
20290 #endif
20291 
20292 /******************************************************************************/
20293 
20294 #ifndef WITH_LEANER
20295 static void
20297 {
20299  {
20300  char *s = soap->mime.boundary;
20301  size_t n = 0;
20302  if (s)
20303  n = strlen(s);
20304  if (n < 16)
20305  {
20306  n = 64;
20307  s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
20308  if (!s)
20309  return;
20310  }
20311  *s++ = '=';
20312  *s++ = '=';
20313  n -= 4;
20314  while (n)
20315  {
20316  *s++ = soap_base64o[soap_random & 0x3F];
20317  n--;
20318  }
20319  *s++ = '=';
20320  *s++ = '=';
20321  *s = '\0';
20322  }
20323  if (!soap->mime.start)
20324  soap->mime.start = "<SOAP-ENV:Envelope>";
20325 }
20326 #endif
20327 
20328 /******************************************************************************/
20329 
20330 #ifndef WITH_LEANER
20331 static int
20333 {
20334  struct soap_multipart *content;
20335  size_t k;
20336  if (soap->fmimeread)
20337  return SOAP_OK;
20338  k = strlen(soap->mime.boundary);
20339  for (content = soap->mime.first; content; content = content->next)
20340  {
20341  if (content->ptr && content->size >= k)
20342  {
20343  const char *p = (const char*)content->ptr;
20344  size_t i;
20345  for (i = 0; i < content->size - k; i++, p++)
20346  {
20347  if (!strncmp(p, soap->mime.boundary, k))
20348  return SOAP_ERR;
20349  }
20350  }
20351  }
20352  return SOAP_OK;
20353 }
20354 #endif
20355 
20356 /******************************************************************************/
20357 
20358 #ifdef WITH_GZIP
20359 static int
20360 soap_getgziphdr(struct soap *soap)
20361 {
20362  int i;
20363  soap_wchar c = 0, f = 0;
20364  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
20365  for (i = 0; i < 9; i++)
20366  {
20367  c = soap_get1(soap);
20368  if (i == 1 && c == 8)
20369  soap->z_dict = 0;
20370  if (i == 2)
20371  f = c;
20372  }
20373  if (f & 0x04) /* FEXTRA */
20374  {
20375  i = soap_get1(soap);
20376  i |= soap_get1(soap) << 8;
20377  while (i-- > 0)
20378  {
20379  if ((int)soap_get1(soap) == EOF)
20380  return soap->error = SOAP_ZLIB_ERROR;
20381  }
20382  }
20383  if (f & 0x08) /* skip FNAME */
20384  {
20385  do
20386  {
20387  c = soap_get1(soap);
20388  } while (c && (int)c != EOF);
20389  }
20390  if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
20391  {
20392  do
20393  {
20394  c = soap_get1(soap);
20395  } while (c && (int)c != EOF);
20396  }
20397  if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
20398  {
20399  c = soap_get1(soap);
20400  if ((int)c != EOF)
20401  c = soap_get1(soap);
20402  }
20403  if ((int)c == EOF)
20404  return soap->error = SOAP_ZLIB_ERROR;
20405  return SOAP_OK;
20406 }
20407 #endif
20408 
20409 /******************************************************************************/
20410 
20411 SOAP_FMAC1
20412 int
20413 SOAP_FMAC2
20415 {
20416 #ifdef WITH_FASTCGI
20417  if (FCGI_Accept() < 0)
20418  {
20419  soap->error = SOAP_EOF;
20420  return soap_send_fault(soap);
20421  }
20422 #endif
20423  soap_begin(soap);
20424  if (soap_begin_recv(soap)
20428  {
20429  if (soap->error < SOAP_STOP)
20430  {
20431 #ifdef WITH_FASTCGI
20432  (void)soap_send_fault(soap);
20433 #else
20434  return soap_send_fault(soap);
20435 #endif
20436  }
20437  return soap_closesock(soap);
20438  }
20439  return SOAP_OK;
20440 }
20441 
20442 /******************************************************************************/
20443 
20444 SOAP_FMAC1
20445 int
20446 SOAP_FMAC2
20448 {
20449  soap_wchar c;
20450  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", (int)soap->socket, soap->recvfd));
20451  soap->error = SOAP_OK;
20452 #ifndef WITH_LEANER
20453  soap->recverror = SOAP_OK;
20454 #endif
20457  soap->version = 0; /* don't assume we're parsing SOAP content by default */
20458 #ifndef WITH_NOIDREF
20460 #endif
20461  if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
20462  {
20463  soap->imode &= ~SOAP_IO;
20465  }
20467  soap->mode = soap->imode;
20468  if (!(soap->mode & SOAP_IO_KEEPALIVE))
20469  soap->keep_alive = 0;
20470  if (!soap->keep_alive)
20471  soap->buflen = soap->bufidx = 0;
20472  soap->null = 0;
20473  soap->position = 0;
20474  soap->mustUnderstand = 0;
20475  soap->shaky = 0;
20476  soap->ahead = 0;
20477  soap->peeked = 0;
20478  soap->level = 0;
20480  soap->count = 0;
20481  soap->length = 0;
20482  soap->cdata = 0;
20483  *soap->endpoint = '\0';
20484  soap->action = NULL;
20485  soap->header = NULL;
20486  soap->fault = NULL;
20487  soap->status = 0;
20488  soap->fform = NULL;
20489  soap->body = 1;
20490 #ifndef WITH_LEANER
20491  soap->dom = NULL;
20492  soap->dime.count = 0;
20493  soap->dime.chunksize = 0;
20494  soap->dime.buflen = 0;
20495  soap->dime.list = NULL;
20496  soap->dime.first = NULL;
20497  soap->dime.last = NULL;
20498  soap->mime.list = NULL;
20499  soap->mime.first = NULL;
20500  soap->mime.last = NULL;
20501  soap->mime.boundary = NULL;
20502  soap->mime.start = NULL;
20503 #endif
20504 #ifdef WIN32
20505 #ifndef UNDER_CE
20506 #ifndef WITH_FASTCGI
20507  if (!soap_valid_socket(soap->socket) && !soap->is && soap->recvfd >= 0) /* Set win32 stdin or soap->recvfd to BINARY, e.g. to support DIME */
20508 #ifdef __BORLANDC__
20509  setmode(soap->recvfd, _O_BINARY);
20510 #else
20511  _setmode(soap->recvfd, _O_BINARY);
20512 #endif
20513 #endif
20514 #endif
20515 #endif
20516 #ifdef WITH_ZLIB
20519  if (!soap->d_stream)
20520  {
20521  soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
20522  if (!soap->d_stream)
20523  return soap->error = SOAP_EOM;
20524  soap->d_stream->zalloc = Z_NULL;
20525  soap->d_stream->zfree = Z_NULL;
20526  soap->d_stream->opaque = Z_NULL;
20527  soap->d_stream->next_in = Z_NULL;
20528  soap->d_stream->msg = Z_NULL;
20529  }
20530  soap->d_stream->avail_in = 0;
20531  soap->d_stream->next_out = (Byte*)soap->buf;
20532  soap->d_stream->avail_out = sizeof(soap->buf);
20533  soap->z_ratio_in = 1.0;
20534 #endif
20535 #ifdef WITH_OPENSSL
20536  if (soap->ssl)
20537  ERR_clear_error();
20538 #endif
20539 #ifndef WITH_LEAN
20540  soap->start = (ULONG64)time(NULL);
20541 #endif
20542 #ifndef WITH_LEANER
20544  return soap->error;
20545 #endif
20546  c = soap_getchar(soap);
20547 #ifdef WITH_GZIP
20548  if (c == 0x1F)
20549  {
20550  if (soap_getgziphdr(soap))
20551  return soap->error;
20553  return soap->error = SOAP_ZLIB_ERROR;
20554  if (soap->z_dict)
20555  {
20557  return soap->error = SOAP_ZLIB_ERROR;
20558  }
20560  soap->mode |= SOAP_ENC_ZLIB;
20562  soap->z_crc = crc32(0L, NULL, 0);
20563  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
20564  if (!soap->z_buf)
20565  soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
20566  (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
20567  /* should not chunk over plain transport, so why bother to check? */
20568  /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
20569  /* soap->z_buflen = soap->bufidx; */
20570  /* else */
20571  soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
20572  soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
20573  soap->z_buflen = soap->buflen;
20574  soap->buflen = soap->bufidx;
20575  c = ' ';
20576  }
20577 #endif
20578  while (soap_coblank(c))
20579  c = soap_getchar(soap);
20580 #ifndef WITH_LEANER
20581  if (c == '-' && soap_get0(soap) == '-')
20582  {
20583  soap->mode |= SOAP_ENC_MIME;
20584  }
20585  else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
20586  {
20587  soap->mode |= SOAP_ENC_DIME;
20588  }
20589  else
20590 #endif
20591  {
20592  /* skip BOM */
20593  if (c == 0xEF && soap_get0(soap) == 0xBB)
20594  {
20595  soap_get1(soap);
20596  c = soap_get1(soap);
20597  if (c == 0xBF)
20598  {
20599  soap->mode &= ~SOAP_ENC_LATIN;
20600  c = soap_getchar(soap);
20601  }
20602  else
20603  {
20604  c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */
20605  }
20606  }
20607  else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
20608  || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
20609  {
20610  return soap->error = SOAP_UTF_ERROR;
20611  }
20612  /* skip space */
20613  while (soap_coblank(c))
20614  c = soap_getchar(soap);
20615  }
20616  if ((int)c == EOF)
20617  return soap->error = SOAP_CHK_EOF;
20618  soap_unget(soap, c);
20619 #ifndef WITH_NOHTTP
20620  /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
20621  if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_PLAIN)))
20622  {
20623  soap_mode m = soap->imode;
20624  soap->error = soap->fparse(soap);
20625  soap->mode = soap->imode; /* if imode is changed, effectuate */
20626  soap->imode = m; /* restore imode */
20627  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
20628  {
20630  soap->buflen = soap->bufidx;
20631  soap->chunksize = 0;
20632  }
20633 #ifdef WITH_ZLIB
20634  soap->mode &= ~SOAP_ENC_ZLIB;
20635  if (soap->zlib_in != SOAP_ZLIB_NONE)
20636  {
20637 #ifdef WITH_GZIP
20638  if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
20639  {
20640  c = soap_get1(soap);
20641  if (c == (int)EOF)
20642  return soap->error = SOAP_EOF;
20643  if (c == 0x1F)
20644  {
20645  if (soap_getgziphdr(soap))
20646  return soap->error;
20648  return soap->error = SOAP_ZLIB_ERROR;
20649  soap->z_crc = crc32(0L, NULL, 0);
20650  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
20651  }
20652  else
20653  {
20654  soap_revget1(soap);
20655  if (inflateInit(soap->d_stream) != Z_OK)
20656  return soap->error = SOAP_ZLIB_ERROR;
20658  }
20659  }
20660  else
20661 #endif
20662  if (inflateInit(soap->d_stream) != Z_OK)
20663  return soap->error = SOAP_ZLIB_ERROR;
20664  if (soap->z_dict)
20665  {
20667  return soap->error = SOAP_ZLIB_ERROR;
20668  }
20670  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
20671  soap->mode |= SOAP_ENC_ZLIB;
20672  if (!soap->z_buf)
20673  soap->z_buf = (char*)SOAP_MALLOC(soap, sizeof(soap->buf));
20674  (void)soap_memcpy((void*)soap->z_buf, sizeof(soap->buf), (const void*)soap->buf, sizeof(soap->buf));
20675  soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
20676  soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
20677  soap->z_buflen = soap->buflen;
20678  soap->buflen = soap->bufidx;
20679  }
20680 #endif
20681 #ifndef WITH_LEANER
20683  {
20684  int r;
20685  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n"));
20687  if (r)
20688  return soap->error = r;
20689  }
20690 #endif
20691  if (soap->error && soap->error < SOAP_STOP)
20692  {
20693  if (soap->status >= 200 && soap->status < 600)
20694  {
20695  const char *s = soap_http_get_body(soap, NULL);
20696  (void)soap_end_recv(soap);
20697  if (soap->status >= 300)
20698  soap->keep_alive = 0; /* to force close */
20699  return soap_set_receiver_error(soap, "HTTP Error", s, soap->status);
20700  }
20701  return soap->error;
20702  }
20703  if (!soap->body && soap->status >= 200 && soap->status < 600)
20704  return soap->error = soap->status; /* client side received HTTP status code */
20705  if (soap->status > SOAP_POST)
20706  {
20707  soap->fform = NULL;
20708  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http method handler\n"));
20709  switch (soap->status)
20710  {
20711  case SOAP_GET:
20713  return soap->error;
20714  soap->error = soap->fget(soap);
20715  break;
20716  case SOAP_PUT:
20717  soap->error = soap->fput(soap);
20718  break;
20719  case SOAP_PATCH:
20720  soap->error = soap->fpatch(soap);
20721  break;
20722  case SOAP_DEL:
20724  return soap->error;
20725  soap->error = soap->fdel(soap);
20726  break;
20727  case SOAP_HEAD:
20729  return soap->error;
20730  soap->error = soap->fhead(soap);
20731  break;
20732  case SOAP_OPTIONS:
20734  return soap->error;
20735  soap->error = soap->fopt(soap);
20736  break;
20737  default:
20739  return soap->error;
20740  return 405;
20741  }
20742  if (soap->error == SOAP_OK)
20743  return soap->error = SOAP_STOP; /* prevents further processing */
20744  if (soap->error != SOAP_FORM || !soap->fform) /* continue if handler returned SOAP_FORM */
20745  return soap->error;
20746  soap->error = SOAP_OK;
20747  }
20748  if (soap->fform)
20749  {
20750  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking http form handler\n"));
20751  soap->error = soap->fform(soap);
20752  if (soap->error == SOAP_OK)
20753  return soap->error = SOAP_STOP; /* prevents further processing */
20754  if (soap->status != SOAP_POST || soap->error != 404) /* continue with POST if handler returned HTTP not found */
20755  return soap->error;
20756  soap->error = SOAP_OK;
20757  }
20758  if (!soap->body)
20759  return soap->error = SOAP_NO_DATA;
20760  }
20761 #endif
20762 #ifndef WITH_LEANER
20763  if ((soap->mode & SOAP_ENC_MIME))
20764  {
20765  do /* skip preamble */
20766  {
20767  c = soap_getchar(soap);
20768  if ((int)c == EOF)
20769  return soap->error = SOAP_CHK_EOF;
20770  } while (c != '-' || soap_get0(soap) != '-');
20771  soap_unget(soap, c);
20772  if (soap_getmimehdr(soap))
20773  return soap->error;
20774  if (soap->mime.start)
20775  {
20776  do
20777  {
20778  if (!soap->mime.last->id)
20779  break;
20781  break;
20782  } while (soap_recv_mime_attachment(soap, NULL));
20783  }
20784  if (soap_http_header_attribute(soap, soap->mime.first->type, "application/dime"))
20785  soap->mode |= SOAP_ENC_DIME;
20786  }
20787  if ((soap->mode & SOAP_ENC_DIME))
20788  {
20789  if (soap_getdimehdr(soap))
20790  return soap->error;
20791  if ((soap->dime.flags & SOAP_DIME_CF))
20792  {
20793  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked SOAP in DIME message\n"));
20795  if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
20796  {
20797  soap->dime.buflen = soap->buflen;
20799  }
20800  else
20801  {
20803  }
20804  }
20805  soap->count = soap->buflen - soap->bufidx;
20807  return soap->error = SOAP_EOF;
20808  }
20809 #endif
20810  return SOAP_OK;
20811 }
20812 
20813 /******************************************************************************/
20814 
20815 SOAP_FMAC1
20816 int
20817 SOAP_FMAC2
20819 {
20820  if (soap->version == 0)
20821  return SOAP_OK;
20823  return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
20824 }
20825 
20826 /******************************************************************************/
20827 
20828 SOAP_FMAC1
20829 int
20830 SOAP_FMAC2
20832 {
20833  if (soap->version == 0)
20834  return SOAP_OK;
20835  if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
20836  || soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */
20837  return soap->error;
20839  return SOAP_OK;
20840 }
20841 
20842 /******************************************************************************/
20843 
20844 SOAP_FMAC1
20845 int
20846 SOAP_FMAC2
20848 {
20849  return soap->length || (soap->mode & SOAP_ENC_ZLIB) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK;
20850 }
20851 
20852 /******************************************************************************/
20853 
20854 SOAP_FMAC1
20855 int
20856 SOAP_FMAC2
20858 {
20859  ULONG64 k = soap->length;
20860  /* check HTTP body, return "" if none */
20861  if (!k && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
20862  return SOAP_OK;
20863  /* do not consume DIME or MIME attachments, leave this to soap_end_recv */
20864  if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME))
20865  return SOAP_OK;
20866  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skipping HTTP body (mode=0x%x)\n", soap->mode));
20867  if (k && !(soap->mode & SOAP_ENC_ZLIB))
20868  {
20869  size_t i;
20870  soap->length = 0;
20871  for (i = 0; i < k; i++)
20872  {
20874  if ((int)c == EOF)
20875  break;
20876  }
20877  }
20878  else
20879  {
20880  for (;;)
20881  {
20883  if ((int)c == EOF)
20884  break;
20885  }
20886  }
20887  return SOAP_OK;
20888 }
20889 
20890 /******************************************************************************/
20891 
20892 SOAP_FMAC1
20893 char *
20894 SOAP_FMAC2
20895 soap_http_get_body(struct soap *soap, size_t *len)
20896 {
20897  return soap_http_get_body_prefix(soap, len, NULL);
20898 }
20899 
20900 /******************************************************************************/
20901 
20902 SOAP_FMAC1
20903 char *
20904 SOAP_FMAC2
20906 {
20907  return soap_http_get_body_prefix(soap, NULL, "?");
20908 }
20909 
20910 /******************************************************************************/
20911 
20912 SOAP_FMAC1
20913 char *
20914 SOAP_FMAC2
20915 soap_http_get_body_prefix(struct soap *soap, size_t *len, const char *prefix)
20916 {
20917  char *s;
20918  ULONG64 k = soap->length;
20919  size_t n = 0;
20920  if (!prefix)
20921  prefix = SOAP_STR_EOS;
20922  else
20923  n = strlen(prefix);
20924  if (len)
20925  *len = 0;
20926  /* check HTTP body, return "" if none */
20927  if (!k && !(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
20928  return soap_strdup(soap, prefix);
20929  /* do not consume DIME or MIME attachments, leave this to soap_end_recv */
20930  if ((soap->mode & SOAP_ENC_DIME) || (soap->mode & SOAP_ENC_MIME))
20931  return soap_strdup(soap, prefix);
20932  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing HTTP body, prefixed with '%s' (mode=0x%x)\n", prefix, soap->mode));
20933  if (k && !(soap->mode & SOAP_ENC_ZLIB))
20934  {
20935  char *t;
20936  soap->length = 0;
20937  /* http content length != 0 and uncompressed body */
20938  if ((SOAP_MAXALLOCSIZE != 0 && n + k > SOAP_MAXALLOCSIZE) || n + k > (ULONG64)((size_t)-2))
20939  {
20940  soap->error = SOAP_EOM;
20941  return NULL;
20942  }
20943  s = t = (char*)soap_malloc(soap, (size_t)k + n + 1);
20944  if (s)
20945  {
20946  size_t i;
20947  soap_strcpy(t, n + 1, prefix);
20948  t += n;
20949  for (i = 0; i < k; i++)
20950  {
20952  if ((int)c == EOF)
20953  break;
20954  *t++ = (char)(c & 0xFF);
20955  }
20956  *t = '\0';
20957  if (len)
20958  *len = n + i;
20959  }
20960  else
20961  {
20962  soap->error = SOAP_EOM;
20963  return NULL;
20964  }
20965  }
20966  else
20967  {
20968  size_t i, l = 0;
20969  if (soap_alloc_block(soap) == NULL)
20970  return NULL;
20971  if (n)
20972  {
20973  s = (char*)soap_push_block(soap, NULL, n);
20974  if (!s)
20975  return NULL;
20976  soap_strcpy(s, n + 1, prefix);
20977  l += n;
20978  }
20979  for (;;)
20980  {
20981  size_t k = SOAP_BLKLEN;
20982  s = (char*)soap_push_block(soap, NULL, k);
20983  if (!s)
20984  return NULL;
20985  for (i = 0; i < k; i++)
20986  {
20987  soap_wchar c;
20988  l++;
20989  if (l == 0)
20990  {
20991  soap->error = SOAP_EOM;
20992  return NULL;
20993  }
20994  c = soap_get1(soap);
20995  if ((int)c == EOF)
20996  goto end;
20997  *s++ = (char)(c & 0xFF);
20998  }
20999  }
21000 end:
21001  *s = '\0';
21002  if (len)
21003  *len = l - 1;
21004  soap_size_block(soap, NULL, i + 1);
21005  s = soap_save_block(soap, NULL, NULL, 0);
21006  }
21007  return s;
21008 }
21009 
21010 /******************************************************************************/
21011 
21012 SOAP_FMAC1
21013 int
21014 SOAP_FMAC2
21016 {
21018  if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
21019  {
21020  if (soap->error == SOAP_TAG_MISMATCH)
21021  {
21022  if (!soap_element_begin_in(soap, "Envelope", 0, NULL))
21024  else if (soap->status == 0
21025  || (soap->status >= 200 && soap->status <= 299)
21026  || soap->status == 400
21027  || soap->status == 500)
21028  return SOAP_OK; /* allow non-SOAP (REST) XML content to be captured */
21029  soap->error = soap->status;
21030  }
21031  else if (soap->status)
21032  {
21033  soap->error = soap->status;
21034  }
21035  return soap->error;
21036  }
21037  soap_version(soap);
21038  return SOAP_OK;
21039 }
21040 
21041 /******************************************************************************/
21042 
21043 SOAP_FMAC1
21044 int
21045 SOAP_FMAC2
21047 {
21048  if (soap->version == 0)
21049  return SOAP_OK;
21051  return soap_element_end_in(soap, "SOAP-ENV:Envelope");
21052 }
21053 
21054 /******************************************************************************/
21055 
21056 SOAP_FMAC1
21057 int
21058 SOAP_FMAC2
21060 {
21061  if (soap->version == 1)
21062  soap->encoding = 1;
21063 #ifndef WITH_LEAN
21064  if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
21065  return soap->error;
21066 #endif
21067  if (soap->version == 0)
21068  return SOAP_OK;
21069  soap->part = SOAP_IN_BODY;
21070  return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
21071 }
21072 
21073 /******************************************************************************/
21074 
21075 SOAP_FMAC1
21076 int
21077 SOAP_FMAC2
21079 {
21080  if (soap->version == 0)
21081  return SOAP_OK;
21082  if (soap_element_end_out(soap, "SOAP-ENV:Body"))
21083  return soap->error;
21084  soap->part = SOAP_END_BODY;
21085  return SOAP_OK;
21086 }
21087 
21088 /******************************************************************************/
21089 
21090 SOAP_FMAC1
21091 int
21092 SOAP_FMAC2
21094 {
21095  if (soap->version == 0)
21096  return SOAP_OK;
21097  soap->part = SOAP_IN_BODY;
21098  if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
21099  return soap->error;
21100  if (!soap->body)
21101  soap->part = SOAP_NO_BODY;
21102  return SOAP_OK;
21103 }
21104 
21105 /******************************************************************************/
21106 
21107 SOAP_FMAC1
21108 int
21109 SOAP_FMAC2
21111 {
21112  if (soap->version == 0)
21113  return SOAP_OK;
21114  if (soap->part == SOAP_NO_BODY)
21115  return soap->error = SOAP_OK;
21116  soap->part = SOAP_END_BODY;
21117  return soap_element_end_in(soap, "SOAP-ENV:Body");
21118 }
21119 
21120 /******************************************************************************/
21121 
21122 SOAP_FMAC1
21123 int
21124 SOAP_FMAC2
21126 {
21128  soap->error = SOAP_OK;
21129  if (soap->error == SOAP_OK && soap->fheader)
21130  soap->error = soap->fheader(soap);
21131  return soap->error;
21132 }
21133 
21134 /******************************************************************************/
21135 
21136 SOAP_FMAC1
21137 void
21138 SOAP_FMAC2
21139 soap_set_endpoint(struct soap *soap, const char *endpoint)
21140 {
21141  const char *s, *t;
21142  size_t i, n;
21143  soap->endpoint[0] = '\0';
21144  soap->host[0] = '\0';
21145  soap->path[0] = '/';
21146  soap->path[1] = '\0';
21147  soap->port = 80;
21148  if (!endpoint || !*endpoint)
21149  return;
21150 #ifdef WITH_OPENSSL
21151  if (!soap_tag_cmp(endpoint, "https:*"))
21152  soap->port = 443;
21153 #endif
21154  soap_strcpy(soap->endpoint, sizeof(soap->endpoint), endpoint);
21155  s = strchr(endpoint, ':');
21156  if (s && s[1] == '/' && s[2] == '/')
21157  s += 3;
21158  else
21159  s = endpoint;
21160 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
21161  t = strchr(s, '@');
21162  if (t && *s != ':' && *s != '@')
21163  {
21164  size_t l = t - s + 1;
21165  char *r = (char*)soap_malloc(soap, l);
21166  n = s - endpoint;
21167  if (r)
21168  {
21169  s = soap_decode(r, l, s, ":@");
21170  soap->userid = r;
21172  if (*s == ':')
21173  {
21174  s++;
21175  if (*s != '@')
21176  {
21177  l = t - s + 1;
21178  r = r + strlen(r) + 1;
21179  s = soap_decode(r, l, s, "@");
21180  soap->passwd = r;
21181  }
21182  }
21183  }
21184  s++;
21185  soap_strcpy(soap->endpoint + n, sizeof(soap->endpoint) - n, s);
21186  }
21187 #endif
21188  n = strlen(s);
21189  if (n >= sizeof(soap->host))
21190  n = sizeof(soap->host) - 1;
21191 #ifdef WITH_IPV6
21192  if (s[0] == '[')
21193  {
21194  s++;
21195  for (i = 0; i < n; i++)
21196  {
21197  if (s[i] == ']')
21198  {
21199  s++;
21200  --n;
21201  break;
21202  }
21203  soap->host[i] = s[i];
21204  }
21205  }
21206  else
21207  {
21208  for (i = 0; i < n; i++)
21209  {
21210  soap->host[i] = s[i];
21211  if (s[i] == '/' || s[i] == ':' || s[i] == '?')
21212  break;
21213  }
21214  }
21215 #else
21216  for (i = 0; i < n; i++)
21217  {
21218  soap->host[i] = s[i];
21219  if (s[i] == '/' || s[i] == ':' || s[i] == '?')
21220  break;
21221  }
21222 #endif
21223  soap->host[i] = '\0';
21224  if (s[i] == ':')
21225  {
21226  soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
21227  for (i++; i < n; i++)
21228  if (s[i] == '/')
21229  break;
21230  }
21231  if (i < n && s[i])
21232  soap_strcpy(soap->path, sizeof(soap->path), s + i);
21234  {
21236  if (soap->override_port)
21238  }
21239  if (soap->userid && !soap->authrealm)
21240  soap->authrealm = soap->host;
21241 }
21242 
21243 /******************************************************************************/
21244 
21245 #ifndef WITH_NOHTTP
21246 SOAP_FMAC1
21247 int
21248 SOAP_FMAC2
21249 soap_GET(struct soap *soap, const char *endpoint, const char *action)
21250 {
21251  return soap_connect_command(soap, SOAP_GET, endpoint, action);
21252 }
21253 #endif
21254 
21255 /******************************************************************************/
21256 
21257 #ifndef WITH_NOHTTP
21258 SOAP_FMAC1
21259 int
21260 SOAP_FMAC2
21261 soap_PUT(struct soap *soap, const char *endpoint, const char *action, const char *type)
21262 {
21263  soap->http_content = type;
21264  if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK)
21265  {
21266  soap->omode &= ~SOAP_IO;
21267  soap->omode |= SOAP_IO_STORE;
21268  }
21269  return soap_connect_command(soap, SOAP_PUT, endpoint, action);
21270 }
21271 #endif
21272 
21273 /******************************************************************************/
21274 
21275 #ifndef WITH_NOHTTP
21276 SOAP_FMAC1
21277 int
21278 SOAP_FMAC2
21279 soap_POST(struct soap *soap, const char *endpoint, const char *action, const char *type)
21280 {
21281  soap->http_content = type;
21282  if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK)
21283  {
21284  soap->omode &= ~SOAP_IO;
21285  soap->omode |= SOAP_IO_STORE;
21286  }
21287  return soap_connect_command(soap, SOAP_POST_FILE, endpoint, action);
21288 }
21289 #endif
21290 
21291 /******************************************************************************/
21292 
21293 #ifndef WITH_NOHTTP
21294 SOAP_FMAC1
21295 int
21296 SOAP_FMAC2
21297 soap_PATCH(struct soap *soap, const char *endpoint, const char *action, const char *type)
21298 {
21299  soap->http_content = type;
21300  if ((soap->omode & SOAP_IO) != SOAP_IO_CHUNK)
21301  {
21302  soap->omode &= ~SOAP_IO;
21303  soap->omode |= SOAP_IO_STORE;
21304  }
21305  return soap_connect_command(soap, SOAP_PATCH, endpoint, action);
21306 }
21307 #endif
21308 
21309 /******************************************************************************/
21310 
21311 #ifndef WITH_NOHTTP
21312 SOAP_FMAC1
21313 int
21314 SOAP_FMAC2
21315 soap_DELETE(struct soap *soap, const char *endpoint)
21316 {
21317  if (soap_connect_command(soap, SOAP_DEL, endpoint, NULL)
21319  return soap_closesock(soap);
21320  return SOAP_OK;
21321 }
21322 #endif
21323 
21324 /******************************************************************************/
21325 
21326 SOAP_FMAC1
21327 int
21328 SOAP_FMAC2
21329 soap_connect(struct soap *soap, const char *endpoint, const char *action)
21330 {
21331  return soap_connect_command(soap, SOAP_POST, endpoint, action);
21332 }
21333 
21334 /******************************************************************************/
21335 
21336 SOAP_FMAC1
21337 int
21338 SOAP_FMAC2
21339 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
21340 {
21341  if (endpoints)
21342  {
21343  int retry = soap->connect_retry;
21344  unsigned int backoff = 1;
21345  for (;;)
21346  {
21347  struct timeval tv;
21348  const char *s;
21349  s = strchr(endpoints, ' ');
21350  if (s)
21351  {
21352  size_t l = strlen(endpoints);
21353  char *endpoint = NULL;
21354  if (SOAP_MAXALLOCSIZE == 0 || l <= SOAP_MAXALLOCSIZE)
21355  endpoint = (char*)SOAP_MALLOC(soap, l + 1);
21356  if (!endpoint)
21357  return soap->error = SOAP_EOM;
21358  for (;;)
21359  {
21360  (void)soap_strncpy(endpoint, l + 1, endpoints, s - endpoints);
21361  endpoint[s - endpoints] = '\0';
21362  if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
21363  break;
21364  while (*s == ' ')
21365  s++;
21366  if (!*s)
21367  break;
21368  soap->error = SOAP_OK;
21369  endpoints = s;
21370  s = strchr(endpoints, ' ');
21371  if (!s)
21372  s = endpoints + strlen(endpoints);
21373  }
21374  SOAP_FREE(soap, endpoint);
21375  }
21376  else
21377  {
21378  soap_try_connect_command(soap, http_command, endpoints, action);
21379  }
21380  if (soap->error != SOAP_TCP_ERROR || retry <= 0)
21381  break;
21382  soap->error = SOAP_OK;
21383  tv.tv_sec = backoff;
21384  tv.tv_usec = 0;
21385  select(0, NULL, NULL, NULL, &tv);
21386  if (backoff < 32)
21387  backoff *= 2;
21388  --retry;
21389  }
21390  }
21391  return soap->error;
21392 }
21393 
21394 /******************************************************************************/
21395 
21396 static int
21397 soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
21398 {
21399  char host[sizeof(soap->host)];
21400  int port;
21401  ULONG64 count;
21402  soap->error = SOAP_OK;
21404  soap->errnum = 0;
21405  (void)soap_memcpy(host, sizeof(host), soap->host, sizeof(soap->host)); /* save previous host name: if != then reconnect */
21406  port = soap->port; /* save previous port to compare */
21407  soap->status = http_command;
21408  soap_set_endpoint(soap, endpoint);
21409  soap->action = soap_strdup(soap, action);
21410 #ifndef WITH_LEANER
21411  if (soap->fconnect)
21412  {
21413  soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port);
21414  if (soap->error)
21415  return soap->error;
21416  }
21417  else
21418 #endif
21419  if (soap->fopen && *soap->host)
21420  {
21421  if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
21422  {
21423  soap->error = SOAP_OK;
21424 #ifndef WITH_LEAN
21425  if (!strncmp(endpoint, "soap.udp:", 9) || !strncmp(endpoint, "udp:", 4))
21426  {
21427  soap->omode |= SOAP_IO_UDP;
21428  }
21429  else
21430 #endif
21431  {
21432  soap->keep_alive = 0; /* to force close */
21433  soap->omode &= ~SOAP_IO_UDP; /* to force close */
21434  }
21436  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint?endpoint:"(null)", soap->host, soap->path, soap->port));
21438  {
21439  soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
21440  if (!soap_valid_socket(soap->socket) || soap->error)
21441  {
21442  if (soap->error)
21443  return soap->error;
21444  return soap->error = SOAP_TCP_ERROR;
21445  }
21446  soap->keep_alive = -((soap->omode & SOAP_IO_KEEPALIVE) != 0);
21447  }
21448  }
21449  }
21450 #ifdef WITH_NTLM
21451  if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port))
21452  return soap->error;
21453 #endif
21455  if (soap_init_send(soap))
21456  return soap->error;
21457 #ifndef WITH_NOHTTP
21458  if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD || http_command == SOAP_OPTIONS)
21459  {
21460  soap->mode &= ~SOAP_IO;
21461  soap->mode |= SOAP_IO_BUFFER;
21462  }
21463  if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_PLAIN) && endpoint)
21464  {
21465  soap_mode k = soap->mode;
21466  soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
21467  if ((k & SOAP_IO) != SOAP_IO_FLUSH)
21468  soap->mode |= SOAP_IO_BUFFER;
21469  soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count);
21470  if (soap->error)
21471  return soap->error;
21472  if ((k & SOAP_IO) == SOAP_IO_CHUNK)
21473  {
21474  if (soap_flush(soap))
21475  return soap->error;
21476  }
21477  soap->mode = k;
21478  }
21479  if (http_command == SOAP_GET || http_command == SOAP_DEL || http_command == SOAP_HEAD || http_command == SOAP_OPTIONS)
21480  return soap_end_send_flush(soap);
21481 #endif
21482 #ifndef WITH_LEANER
21484  return soap->error;
21485 #endif
21486  return SOAP_OK;
21487 }
21488 
21489 /******************************************************************************/
21490 
21491 #ifdef WITH_NTLM
21492 static int
21493 soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port)
21494 {
21495  /* requires libntlm from http://www.nongnu.org/libntlm/ */
21496  const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid);
21497  const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd);
21498  struct SOAP_ENV__Header *oldheader;
21499  if (soap->ntlm_challenge && userid && passwd && soap->authrealm)
21500  {
21501  tSmbNtlmAuthRequest req;
21502  tSmbNtlmAuthResponse res;
21503  tSmbNtlmAuthChallenge ch;
21504  int keep_alive = soap->keep_alive;
21506  ULONG64 count = soap->count;
21507  soap_mode m = soap->mode;
21508  soap_mode om = soap->omode;
21509  int status = soap->status;
21510  char *action = soap->action;
21511  short version = soap->version;
21512  const char *http_content = soap->http_content;
21513  const char *http_extra_header = soap->http_extra_header;
21514  const char *bearer = soap->bearer;
21515  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge));
21516  if (!*soap->ntlm_challenge)
21517  {
21518  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
21519  /* S -> C 401 Unauthorized
21520  WWW-Authenticate: NTLM
21521  */
21522  buildSmbNtlmAuthRequest(&req, userid, soap->authrealm);
21523  soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&req, NULL, SmbLength(&req));
21524  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
21525  /* C -> S GET ...
21526  Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
21527  */
21529  if (soap_init_send(soap))
21530  return soap->error;
21531  if (!soap->keep_alive)
21532  soap->keep_alive = -1; /* client keep alive */
21533  soap->status = command; /* GET or CONNECT for proxy */
21534  if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0)
21536  return soap->error;
21537  soap->mode = m;
21538  soap->keep_alive = keep_alive;
21539  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n"));
21540  oldheader = soap->header;
21541  if (soap_begin_recv(soap))
21542  if (soap->error == SOAP_EOF)
21543  return soap->error;
21544  (void)soap_end_recv(soap);
21545  soap->header = oldheader;
21546  soap->length = length;
21547  if (soap->status != 401 && soap->status != 407)
21548  return soap->error = SOAP_NTLM_ERROR;
21549  soap->error = SOAP_OK;
21550  }
21551  /* S -> C 401 Unauthorized
21552  WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
21553  */
21554  soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL);
21555  buildSmbNtlmAuthResponse(&ch, &res, userid, passwd);
21556  soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)(void*)&res, NULL, SmbLength(&res));
21557  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
21558  /* C -> S GET ...
21559  Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
21560  */
21561  soap->userid = NULL;
21562  soap->passwd = NULL;
21563  soap->proxy_userid = NULL;
21564  soap->proxy_passwd = NULL;
21565  soap->keep_alive = keep_alive;
21566  soap->length = length;
21567  soap->count = count;
21568  soap->mode = m;
21569  soap->omode = om;
21570  soap->status = status;
21571  soap->action = action;
21572  soap->version = version;
21573  soap->http_content = http_content;
21574  soap->http_extra_header = http_extra_header;
21575  soap->bearer = bearer;
21576  }
21577  return SOAP_OK;
21578 }
21579 #endif
21580 
21581 /******************************************************************************/
21582 
21583 SOAP_FMAC1
21584 char*
21585 SOAP_FMAC2
21586 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
21587 {
21588  int i;
21589  unsigned long m;
21590  char *p;
21591  if (!t)
21592  t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
21593  if (!t)
21594  return NULL;
21595  p = t;
21596  t[0] = '\0';
21597  if (!s)
21598  return p;
21599  for (; n > 2; n -= 3, s += 3)
21600  {
21601  m = s[0];
21602  m = (m << 8) | s[1];
21603  m = (m << 8) | s[2];
21604  for (i = 4; i > 0; m >>= 6)
21605  t[--i] = soap_base64o[m & 0x3F];
21606  t += 4;
21607  }
21608  t[0] = '\0';
21609  if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
21610  {
21611  m = 0;
21612  for (i = 0; i < n; i++)
21613  m = (m << 8) | *s++;
21614  for (; i < 3; i++)
21615  m <<= 8;
21616  for (i = 4; i > 0; m >>= 6)
21617  t[--i] = soap_base64o[m & 0x3F];
21618  for (i = 3; i > n; i--)
21619  t[i] = '=';
21620  t[4] = '\0';
21621  }
21622  return p;
21623 }
21624 
21625 /******************************************************************************/
21626 
21627 SOAP_FMAC1
21628 const char*
21629 SOAP_FMAC2
21630 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
21631 {
21632  size_t i, j;
21633  soap_wchar c;
21634  unsigned long m;
21635  const char *p;
21636  if (!s || !*s)
21637  {
21638  if (n)
21639  *n = 0;
21640  if (soap->error)
21641  return NULL;
21642  return SOAP_NON_NULL;
21643  }
21644  if (!t)
21645  {
21646  l = (strlen(s) + 3) / 4 * 3 + 1; /* space for raw binary and \0 */
21647  t = (char*)soap_malloc(soap, l);
21648  }
21649  if (!t)
21650  return NULL;
21651  p = t;
21652  if (n)
21653  *n = 0;
21654  for (i = 0; ; i += 3, l -= 3)
21655  {
21656  m = 0;
21657  j = 0;
21658  while (j < 4)
21659  {
21660  c = *s++;
21661  if (c == '=' || !c)
21662  {
21663  if (l >= j - 1)
21664  {
21665  switch (j)
21666  {
21667  case 2:
21668  *t++ = (char)((m >> 4) & 0xFF);
21669  i++;
21670  l--;
21671  break;
21672  case 3:
21673  *t++ = (char)((m >> 10) & 0xFF);
21674  *t++ = (char)((m >> 2) & 0xFF);
21675  i += 2;
21676  l -= 2;
21677  }
21678  }
21679  if (n)
21680  *n = (int)i;
21681  if (l)
21682  *t = '\0';
21683  return p;
21684  }
21685  c -= '+';
21686  if (c >= 0 && c <= 79)
21687  {
21688  int b = soap_base64i[c];
21689  if (b >= 64)
21690  {
21691  soap->error = SOAP_TYPE;
21692  return NULL;
21693  }
21694  m = (m << 6) + b;
21695  j++;
21696  }
21697  else if (!soap_coblank(c + '+'))
21698  {
21699  soap->error = SOAP_TYPE;
21700  return NULL;
21701  }
21702  }
21703  if (l < 3)
21704  {
21705  if (n)
21706  *n = (int)i;
21707  if (l)
21708  *t = '\0';
21709  return p;
21710  }
21711  *t++ = (char)((m >> 16) & 0xFF);
21712  *t++ = (char)((m >> 8) & 0xFF);
21713  *t++ = (char)(m & 0xFF);
21714  }
21715 }
21716 
21717 /******************************************************************************/
21718 
21719 SOAP_FMAC1
21720 char*
21721 SOAP_FMAC2
21722 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
21723 {
21724  char *p;
21725  if (!t)
21726  t = (char*)soap_malloc(soap, 2 * n + 1);
21727  if (!t)
21728  return NULL;
21729  p = t;
21730  t[0] = '\0';
21731  if (s)
21732  {
21733  for (; n > 0; n--)
21734  {
21735  int m = *s++;
21736  *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
21737  m &= 0x0F;
21738  *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
21739  }
21740  }
21741  *t++ = '\0';
21742  return p;
21743 }
21744 
21745 /******************************************************************************/
21746 
21747 SOAP_FMAC1
21748 const char*
21749 SOAP_FMAC2
21750 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
21751 {
21752  const char *p;
21753  if (!s || !*s)
21754  {
21755  if (n)
21756  *n = 0;
21757  if (soap->error)
21758  return NULL;
21759  return SOAP_NON_NULL;
21760  }
21761  if (!t)
21762  {
21763  l = strlen(s) / 2 + 1; /* make sure enough space for \0 */
21764  t = (char*)soap_malloc(soap, l);
21765  }
21766  if (!t)
21767  return NULL;
21768  p = t;
21769  while (l)
21770  {
21771  int d1, d2;
21772  d1 = *s++;
21773  if (!d1)
21774  break;
21775  d2 = *s++;
21776  if (!d2)
21777  break;
21778  *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
21779  l--;
21780  }
21781  if (n)
21782  *n = (int)(t - p);
21783  if (l)
21784  *t = '\0';
21785  return p;
21786 }
21787 
21788 /******************************************************************************/
21789 
21790 #ifndef WITH_NOHTTP
21791 SOAP_FMAC1
21792 const char *
21793 SOAP_FMAC2
21794 soap_http_content_type(struct soap *soap, int status)
21795 {
21796  if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT)
21797  {
21798  const char *s = "text/xml; charset=utf-8";
21799 #ifndef WITH_LEANER
21800  const char *r = NULL;
21801  size_t n;
21802 #endif
21803  if (((status >= SOAP_FILE && status < SOAP_FILE + 600) || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE || soap->status == SOAP_PATCH) && soap->http_content && *soap->http_content && !strchr(soap->http_content, 10) && !strchr(soap->http_content, 13))
21804  s = soap->http_content;
21805  else if (status == SOAP_HTML)
21806  s = "text/html; charset=utf-8";
21807  else if (soap->version == 2)
21808  s = "application/soap+xml; charset=utf-8";
21809  soap->http_content = NULL; /* use http_content once (assign new value before each call) */
21810 #ifndef WITH_LEANER
21811  if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
21812  {
21813  if ((soap->mode & SOAP_ENC_MTOM))
21814  {
21815  if (soap->version == 2)
21816  r = "application/soap+xml";
21817  else
21818  r = "text/xml";
21819  s = "application/xop+xml";
21820  }
21821  else
21822  {
21823  s = "application/dime";
21824  }
21825  }
21826  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
21827  {
21828  const char *t;
21829  size_t l;
21830  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), strlen(soap->mime.boundary) + 53), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
21831  t = strchr(s, ';');
21832  if (t)
21833  n = t - s;
21834  else
21835  n = strlen(s);
21836  l = strlen(soap->tmpbuf);
21837  if (sizeof(soap->tmpbuf) > l + n)
21838  (void)soap_strncpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, s, n);
21839  if (soap->mime.start)
21840  {
21841  l = strlen(soap->tmpbuf);
21842  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(soap->mime.start) + 10), "\"; start=\"%s", soap->mime.start);
21843  }
21844  if (r)
21845  {
21846  l = strlen(soap->tmpbuf);
21847  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, strlen(r) + 15), "\"; start-info=\"%s", r);
21848  }
21849  l = strlen(soap->tmpbuf);
21850  if (sizeof(soap->tmpbuf) > l)
21851  soap_strcpy(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "\"");
21852  }
21853  else
21854  {
21855  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
21856  }
21857  if (status == SOAP_OK && soap->version == 2 && soap->action)
21858  {
21859  size_t l = strlen(soap->tmpbuf);
21860  n = strlen(soap->action);
21861  (SOAP_SNPRINTF(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, n + 11), "; action=\"%s\"", soap->action);
21862  }
21863 #else
21864  soap_strcpy(soap->tmpbuf, sizeof(soap->tmpbuf), s);
21865 #endif
21866  return soap->tmpbuf;
21867  }
21868  return NULL;
21869 }
21870 #endif
21871 
21872 /******************************************************************************/
21873 
21874 #ifndef WITH_NOHTTP
21875 SOAP_FMAC1
21876 int
21877 SOAP_FMAC2
21878 soap_puthttphdr(struct soap *soap, int status, ULONG64 count)
21879 {
21880  int err = SOAP_OK;
21881  if (soap_http_content_type(soap, status))
21882  {
21883  err = soap->fposthdr(soap, "Content-Type", soap->tmpbuf);
21884  if (err)
21885  return err;
21886 #ifdef WITH_ZLIB
21887  if ((soap->omode & SOAP_ENC_ZLIB))
21888  {
21889 #ifdef WITH_GZIP
21890  err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
21891 #else
21892  err = soap->fposthdr(soap, "Content-Encoding", "deflate");
21893 #endif
21894  if (err)
21895  return err;
21896  }
21897 #endif
21898 #ifndef WITH_LEANER
21899  if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
21900  {
21901  err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
21902  }
21903  else
21904 #endif
21905  {
21907  err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
21908  }
21909  if (err)
21910  return err;
21911  }
21912  if (soap->http_extra_header)
21913  {
21914  const char *header = soap->http_extra_header;
21915  soap->http_extra_header = NULL; /* use http_extra_header once (assign new value before each call) */
21916  if (*header)
21917  {
21918  err = soap_send(soap, header);
21919  if (err)
21920  return err;
21921  err = soap_send_raw(soap, "\r\n", 2);
21922  if (err)
21923  return err;
21924  }
21925  }
21926  if (soap->keep_alive)
21927  {
21928  if (soap->keep_alive > 0 && soap->recv_timeout)
21929  {
21930  int t = soap->recv_timeout;
21931  if (t < 0)
21932  t = 1;
21933  (SOAP_SNPRINTF(soap->tmpbuf, sizeof(soap->tmpbuf), 20), "timeout=%d, max=%d", soap->recv_timeout, soap->keep_alive);
21934  err = soap->fposthdr(soap, "Keep-Alive", soap->tmpbuf);
21935  if (err)
21936  return err;
21937  }
21938  return soap->fposthdr(soap, "Connection", "keep-alive");
21939  }
21940  return soap->fposthdr(soap, "Connection", "close");
21941 }
21942 #endif
21943 
21944 /******************************************************************************/
21945 
21946 #ifndef WITH_LEAN
21947 static const char*
21948 soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
21949 {
21950  if (!t)
21951  t = SOAP_STR_EOS;
21952  if (*soap->tag)
21953  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + strlen(soap->tag) + 47), "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag);
21954  else
21955  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(s) + strlen(t) + 33), "Validation constraint violation: %s%s", s, t);
21956  return soap->msgbuf;
21957 }
21958 #endif
21959 
21960 /******************************************************************************/
21961 
21962 SOAP_FMAC1
21963 void
21964 SOAP_FMAC2
21966 {
21967  const char **c;
21968  const char **s;
21969  if (soap->version == 0)
21970  soap_version(soap);
21971  c = soap_faultcode(soap);
21972  s = soap_faultstring(soap);
21973  if (soap->fseterror)
21974  soap->fseterror(soap, c, s);
21975  if (!*c)
21976  {
21977  if (soap->version == 2)
21978  *c = "SOAP-ENV:Sender";
21979  else if (soap->version == 1)
21980  *c = "SOAP-ENV:Client";
21981  else
21982  *c = "";
21983  }
21984  if (*s)
21985  return;
21986  if (soap->error >= SOAP_POST)
21988  switch (soap->error)
21989  {
21990 #ifndef WITH_LEAN
21991  case SOAP_CLI_FAULT:
21992  *s = "Client fault";
21993  break;
21994  case SOAP_SVR_FAULT:
21995  *s = "Server fault";
21996  break;
21997  case SOAP_TAG_MISMATCH:
21998  *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
21999  break;
22000  case SOAP_TYPE:
22001  if (*soap->type)
22002  *s = soap_set_validation_fault(soap, "type mismatch ", soap->type);
22003  else if (*soap->arrayType)
22004  *s = soap_set_validation_fault(soap, "array type mismatch", NULL);
22005  else
22006  *s = soap_set_validation_fault(soap, "invalid value", NULL);
22007  break;
22008  case SOAP_SYNTAX_ERROR:
22009  *s = soap_set_validation_fault(soap, "syntax error", NULL);
22010  break;
22011  case SOAP_NO_TAG:
22012  if (soap->version == 0 && soap->level == 0)
22013  *s = soap_set_validation_fault(soap, "root element expected", NULL);
22014  else if (soap->level == 0)
22015  *s = soap_set_validation_fault(soap, "SOAP message expected", NULL);
22016  else
22017  *s = soap_set_validation_fault(soap, "element tag expected", NULL);
22018  break;
22019  case SOAP_END_TAG:
22020  *s = soap_set_validation_fault(soap, "closing tag expected", NULL);
22021  break;
22022  case SOAP_MUSTUNDERSTAND:
22023  *c = "SOAP-ENV:MustUnderstand";
22024  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 65), "The data in element '%s' must be understood but cannot be processed", soap->tag);
22025  *s = soap->msgbuf;
22026  break;
22027  case SOAP_VERSIONMISMATCH:
22028  *c = "SOAP-ENV:VersionMismatch";
22029  *s = "Invalid SOAP message or SOAP version mismatch";
22030  break;
22032  *c = "SOAP-ENV:DataEncodingUnknown";
22033  *s = "Unsupported SOAP data encoding";
22034  break;
22035  case SOAP_NAMESPACE:
22036  *s = soap_set_validation_fault(soap, "namespace error", NULL);
22037  break;
22038  case SOAP_USER_ERROR:
22039  *s = "User data access error";
22040  break;
22041  case SOAP_NO_METHOD:
22042  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(soap->tag) + 66), "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
22043  *s = soap->msgbuf;
22044  break;
22045  case SOAP_NO_DATA:
22046  *s = "Data required for operation";
22047  break;
22048  case SOAP_GET_METHOD:
22049  *s = "HTTP GET method not implemented";
22050  break;
22051  case SOAP_PUT_METHOD:
22052  *s = "HTTP PUT method not implemented";
22053  break;
22054  case SOAP_PATCH_METHOD:
22055  *s = "HTTP PATCH method not implemented";
22056  break;
22057  case SOAP_DEL_METHOD:
22058  *s = "HTTP DELETE method not implemented";
22059  break;
22060  case SOAP_HTTP_METHOD:
22061  *s = "HTTP method error";
22062  break;
22063  case SOAP_EOM:
22064  *s = "Out of memory";
22065  break;
22066  case SOAP_MOE:
22067  *s = "Memory overflow or memory corruption error";
22068  break;
22069  case SOAP_HDR:
22070  *s = "Header line too long";
22071  break;
22072  case SOAP_IOB:
22073  *s = "Array index out of bounds";
22074  break;
22075  case SOAP_NULL:
22076  *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
22077  break;
22078  case SOAP_DUPLICATE_ID:
22079  *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id);
22080  if (soap->version == 2)
22081  *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
22082  break;
22083  case SOAP_MISSING_ID:
22084  *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
22085  if (soap->version == 2)
22086  *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
22087  break;
22088  case SOAP_HREF:
22089  *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id);
22090  break;
22091  case SOAP_FAULT:
22092  break;
22093 #ifndef WITH_NOIO
22094  case SOAP_UDP_ERROR:
22095  *s = "Message too large for UDP packet";
22096  break;
22097  case SOAP_TCP_ERROR:
22098  *s = tcp_error(soap);
22099  break;
22100 #endif
22101  case SOAP_HTTP_ERROR:
22102  *s = "An HTTP processing error occurred";
22103  break;
22104  case SOAP_NTLM_ERROR:
22105  *s = "An HTTP NTLM authentication error occurred";
22106  break;
22107  case SOAP_SSL_ERROR:
22108 #ifdef WITH_OPENSSL
22109  *s = "SSL/TLS error";
22110 #else
22111  *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
22112 #endif
22113  break;
22114  case SOAP_PLUGIN_ERROR:
22115  *s = "Plugin registry error";
22116  break;
22117  case SOAP_DIME_ERROR:
22118  *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE currently set to " SOAP_XSTRINGIFY(SOAP_MAXDIMESIZE);
22119  break;
22120  case SOAP_DIME_HREF:
22121  *s = "DIME href to missing attachment";
22122  break;
22123  case SOAP_DIME_MISMATCH:
22124  *s = "DIME version/transmission error";
22125  break;
22126  case SOAP_DIME_END:
22127  *s = "End of DIME error";
22128  break;
22129  case SOAP_MIME_ERROR:
22130  *s = "MIME format error";
22131  break;
22132  case SOAP_MIME_HREF:
22133  *s = "MIME href to missing attachment";
22134  break;
22135  case SOAP_MIME_END:
22136  *s = "End of MIME error";
22137  break;
22138  case SOAP_ZLIB_ERROR:
22139 #ifdef WITH_ZLIB
22140  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), (soap->d_stream && soap->d_stream->msg ? strlen(soap->d_stream->msg) : 0) + 19), "Zlib/gzip error: '%s'", soap->d_stream && soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
22141  *s = soap->msgbuf;
22142 #else
22143  *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
22144 #endif
22145  break;
22146  case SOAP_REQUIRED:
22147  *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
22148  break;
22149  case SOAP_PROHIBITED:
22150  *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
22151  break;
22152  case SOAP_LEVEL:
22153  *s = "Maximum XML nesting depth level exceeded: increase maxlevel";
22154  break;
22155  case SOAP_LENGTH:
22156  *s = soap_set_validation_fault(soap, "value range or content length violation", NULL);
22157  break;
22158  case SOAP_OCCURS:
22159  *s = soap_set_validation_fault(soap, "occurrence constraint violation", NULL);
22160  break;
22161  case SOAP_FIXED:
22162  *s = soap_set_validation_fault(soap, "value does not match the fixed value required", NULL);
22163  break;
22164  case SOAP_EMPTY:
22165  *s = soap_set_validation_fault(soap, "empty value provided where a value is required", NULL);
22166  break;
22167  case SOAP_FD_EXCEEDED:
22168  *s = "Maximum number of open connections was reached: increase FD_SETSIZE or define HAVE_POLL";
22169  break;
22170  case SOAP_UTF_ERROR:
22171  *s = "UTF content encoding error";
22172  break;
22173  case SOAP_STOP:
22174  *s = "Stopped: service request already handled by plugin (informative)";
22175  break;
22176 #endif
22177  case SOAP_EOF:
22178 #ifndef WITH_NOIO
22179  *s = soap_strerror(soap); /* *s = soap->msgbuf */
22180 #ifndef WITH_LEAN
22181  if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
22182  {
22183  (void)soap_memmove((void*)(soap->msgbuf + 25), sizeof(soap->tmpbuf) - 25, (const void*)soap->msgbuf, strlen(soap->msgbuf) + 1);
22184  if (soap->is)
22185 #if defined(__cplusplus) && !defined(WITH_COMPAT)
22186  (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End or bad std::istream: ", 25);
22187 #else
22188  (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End at NUL buffer input: ", 25);
22189 #endif
22190  else
22191  (void)soap_memcpy((void*)soap->msgbuf, sizeof(soap->msgbuf), (const void*)"End of file or no input: ", 25);
22192  }
22193 #endif
22194  break;
22195 #else
22196  *s = "End of file or no input";
22197  break;
22198 #endif
22199  case SOAP_ERR:
22200  *s = "An unspecified error occurred";
22201  break;
22202  default:
22203 #ifndef WITH_NOHTTP
22204 #ifndef WITH_LEAN
22205  if (soap->error >= 200 && soap->error < 600)
22206  {
22207  const char *t = http_error(soap, soap->error);
22208  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), strlen(t) + 54), "Error %d: HTTP %d %s", soap->error, soap->error, t);
22209  *s = soap->msgbuf;
22210  }
22211  else
22212 #endif
22213 #endif
22214  {
22215  (SOAP_SNPRINTF(soap->msgbuf, sizeof(soap->msgbuf), 26), "Error %d", soap->error);
22216  *s = soap->msgbuf;
22217  }
22218  }
22219 }
22220 
22221 /******************************************************************************/
22222 
22223 SOAP_FMAC1
22224 int
22225 SOAP_FMAC2
22227 {
22228  int status = soap->error;
22229  if (status == SOAP_OK || status == SOAP_STOP)
22230  return soap_closesock(soap);
22231 #ifndef WITH_NOHTTP
22232  if (status >= 200 && status <= 299)
22233  return soap_send_empty_response(soap, status);
22234 #endif
22235  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
22236  soap->keep_alive = 0; /* error: close connection later by disabling keep-alive here */
22238  if (soap->error < 200 && soap->error != SOAP_FAULT)
22239  soap->header = NULL;
22240  if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
22241  {
22242  int r = 1;
22243 #ifndef WITH_NOIO
22244  if (soap->fpoll && soap->fpoll(soap))
22245  {
22246  r = 0;
22247  }
22248 #ifndef WITH_LEAN
22249  else if (soap_valid_socket(soap->socket))
22250  {
22252  if (r > 0)
22253  {
22254  int t;
22255  if (!(r & SOAP_TCP_SELECT_SND)
22256  || ((r & SOAP_TCP_SELECT_RCV)
22257  && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0))
22258  r = 0;
22259  }
22260  }
22261 #endif
22262 #endif
22263  if (r > 0)
22264  {
22265  soap->error = SOAP_OK;
22266  if (soap->version > 0)
22267  {
22268  soap->encodingStyle = NULL; /* no encodingStyle in Faults */
22271  (void)soap_begin_count(soap);
22272  if ((soap->mode & SOAP_IO_LENGTH))
22273  {
22275  || soap_putheader(soap)
22277  || soap_putfault(soap)
22280  return soap_closesock(soap);
22281  }
22282  (void)soap_end_count(soap);
22283  if (soap_response(soap, status)
22285  || soap_putheader(soap)
22287  || soap_putfault(soap)
22290  || soap_end_send(soap))
22291  return soap_closesock(soap);
22292  }
22293  else
22294  {
22295  const char *s = *soap_faultstring(soap);
22296  const char **d = soap_faultdetail(soap);
22297  (void)soap_begin_count(soap);
22298  if ((soap->mode & SOAP_IO_LENGTH))
22299  if (soap_element_begin_out(soap, "fault", 0, NULL)
22300  || soap_outstring(soap, "reason", 0, (char*const*)&s, NULL, 0)
22301  || (d && *d && soap_outliteral(soap, "detail", (char*const*)d, NULL))
22302  || soap_element_end_out(soap, "fault"))
22303  return soap_closesock(soap);
22304  (void)soap_end_count(soap);
22305  if (soap_response(soap, status)
22306  || soap_element_begin_out(soap, "fault", 0, NULL)
22307  || soap_outstring(soap, "reason", 0, (char*const*)&s, NULL, 0)
22308  || (d && *d && soap_outliteral(soap, "detail", (char*const*)d, NULL))
22309  || soap_element_end_out(soap, "fault")
22310  || soap_end_send(soap))
22311  return soap_closesock(soap);
22312  }
22313  }
22314  }
22315  soap->error = status;
22316  return soap_closesock(soap);
22317 }
22318 
22319 /******************************************************************************/
22320 
22321 SOAP_FMAC1
22322 int
22323 SOAP_FMAC2
22324 soap_recv_fault(struct soap *soap, int check)
22325 {
22326  int status = soap->status;
22327  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Check (%d) if receiving SOAP Fault (status = %d)\n", check, status));
22328  if (!check)
22329  {
22330  /* try getfault when no tag or tag mismatched at level 2, otherwise close and return SOAP_TAG_MISMATCH or HTTP error code */
22331  if (soap->error != SOAP_NO_TAG && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
22332  {
22333  if (soap->error == SOAP_TAG_MISMATCH && soap->level == 0)
22334  {
22335  soap->error = SOAP_OK;
22336  if (!soap_element_begin_in(soap, "fault", 0, NULL))
22337  {
22338  char *s = NULL, *d = NULL;
22339  (void)soap_instring(soap, "reason", &s, NULL, 0, 1, 0, -1, NULL);
22340  (void)soap_inliteral(soap, "detail", &d);
22341  if (!soap_element_end_in(soap, "fault") && !soap_end_recv(soap))
22342  {
22343  *soap_faultstring(soap) = s;
22344  if (d && *d)
22345  *soap_faultdetail(soap) = d;
22346  if (status)
22347  soap->error = status;
22348  else
22349  soap->error = SOAP_FAULT;
22351  return soap_closesock(soap);
22352  }
22353  }
22355  }
22356  if (status && (status < 200 || status > 299))
22357  soap->error = status;
22358  return soap_closesock(soap);
22359  }
22360  }
22361  soap->error = SOAP_OK;
22362  if (soap_getfault(soap))
22363  {
22364  /* if check>0 and no SOAP Fault is present and no HTTP error then just return to parse request */
22365  if (check
22366  && (status == 0 || (status >= 200 && status <= 299))
22367  && ((soap->error == SOAP_TAG_MISMATCH && soap->level == 2) || soap->error == SOAP_NO_TAG))
22368  return soap->error = SOAP_OK;
22369  /* if check=0 and empty SOAP Body and encodingStyle is NULL and no HTTP error then just return */
22370  if (!check
22371  && (status == 0 || (status >= 200 && status <= 299))
22372  && !soap->encodingStyle
22373  && (soap->error == SOAP_NO_TAG && soap->level <= 2))
22374  return soap->error = SOAP_OK;
22375  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed with error %d at level %u tag '%s'\n", soap->error, soap->level, soap->tag));
22376  *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
22377  if (status)
22378  soap->error = status;
22379  else
22380  soap->error = status = SOAP_NO_DATA;
22382  }
22383  else
22384  {
22385  const char *s = *soap_faultcode(soap);
22386  if (!soap_match_tag(soap, s, "SOAP-ENV:Server")
22387  || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
22388  {
22389  status = SOAP_SVR_FAULT;
22390  }
22391  else if (!soap_match_tag(soap, s, "SOAP-ENV:Client")
22392  || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
22393  {
22394  status = SOAP_CLI_FAULT;
22395  }
22396  else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
22397  {
22398  status = SOAP_MUSTUNDERSTAND;
22399  }
22400  else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
22401  {
22402  status = SOAP_VERSIONMISMATCH;
22403  }
22404  else
22405  {
22406  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
22407  status = SOAP_FAULT;
22408  }
22409  if (!soap_body_end_in(soap))
22411  }
22412  (void)soap_end_recv(soap);
22413  soap->error = status;
22414  return soap_closesock(soap);
22415 }
22416 
22417 /******************************************************************************/
22418 
22419 #ifndef WITH_NOHTTP
22420 SOAP_FMAC1
22421 int
22422 SOAP_FMAC2
22423 soap_send_empty_response(struct soap *soap, int httpstatuscode)
22424 {
22425  soap_mode m = soap->omode;
22426  if (!(m & SOAP_IO_UDP))
22427  {
22428  soap->count = 0;
22429  if ((m & SOAP_IO) == SOAP_IO_CHUNK)
22430  soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
22431  (void)soap_response(soap, httpstatuscode);
22432  (void)soap_end_send(soap); /* force end of sends */
22433  soap->error = SOAP_STOP; /* stops the server from returning another response */
22434  soap->omode = m;
22435  }
22436  return soap_closesock(soap);
22437 }
22438 #endif
22439 
22440 /******************************************************************************/
22441 
22442 #ifndef WITH_NOHTTP
22443 SOAP_FMAC1
22444 int
22445 SOAP_FMAC2
22447 {
22448  soap->error = SOAP_OK;
22449  if (!(soap->omode & SOAP_IO_UDP) && !(soap->omode & SOAP_ENC_PLAIN))
22450  {
22451  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Receiving empty response\n"));
22452  if (soap_begin_recv(soap) == SOAP_OK)
22453  {
22455  return soap_closesock(soap);
22456  }
22457  else if (soap->error == 200 || soap->error == 201 || soap->error == 202)
22458  {
22459  soap->error = SOAP_OK;
22460  }
22461  }
22462 #ifndef WITH_LEANER
22463  else if ((soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
22465  {
22466  return soap->error;
22467  }
22468 #endif
22469  return soap_closesock(soap);
22470 }
22471 #endif
22472 
22473 /******************************************************************************/
22474 
22475 #ifndef WITH_NOIO
22476 static const char*
22478 {
22479  int err = soap->errnum;
22480  *soap->msgbuf = '\0';
22481  if (err)
22482  {
22483 #ifndef WIN32
22484 # ifdef HAVE_STRERROR_R
22485 # if !defined(_GNU_SOURCE) || (!_GNU_SOURCE && ((!defined(_POSIX_C_SOURCE) && !defined(_XOPEN_SOURCE)) || (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600)) || defined(__ANDROID__) || !defined(__GLIBC__))
22486  err = strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */
22487  if (err != 0)
22488  soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "unknown error");
22489 # else
22490  return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */
22491 # endif
22492 # else
22493  return strerror(err);
22494 # endif
22495 #else
22496 #ifndef UNDER_CE
22497  DWORD len;
22498  *soap->msgbuf = '\0';
22499  len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL);
22500 #else
22501  DWORD i, len;
22502  *soap->msgbuf = '\0';
22503  len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
22504  for (i = 0; i <= len; i++)
22505  {
22506  if (((TCHAR*)soap->msgbuf)[i] < 0x80)
22507  soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
22508  else
22509  soap->msgbuf[i] = '?';
22510  }
22511 #endif
22512 #endif
22513  }
22514  else
22515  {
22517  {
22518  soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "max message length exceeded");
22519  }
22520  else
22521  {
22522  int tt = soap->transfer_timeout, rt = soap->recv_timeout, st = soap->send_timeout;
22523 #ifndef WITH_LEAN
22524  int tu = ' ', ru = ' ', su = ' ';
22525 #endif
22526  soap_strcpy(soap->msgbuf, sizeof(soap->msgbuf), "message transfer interrupted");
22527  if (tt | rt || st)
22528  soap_strcpy(soap->msgbuf + 28, sizeof(soap->msgbuf) - 28, " or timed out");
22529 #ifndef WITH_LEAN
22530  if (tt < 0)
22531  {
22532  tt = -tt;
22533  tu = 'u';
22534  }
22535  if (rt < 0)
22536  {
22537  rt = -rt;
22538  ru = 'u';
22539  }
22540  if (st < 0)
22541  {
22542  st = -st;
22543  su = 'u';
22544  }
22545  if (tt)
22546  {
22547  size_t l = strlen(soap->msgbuf);
22548  (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 43), " (%d%csec max transfer time)", tt, tu);
22549  }
22550  if (rt)
22551  {
22552  size_t l = strlen(soap->msgbuf);
22553  (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max recv delay)", rt, ru);
22554  }
22555  if (st)
22556  {
22557  size_t l = strlen(soap->msgbuf);
22558  (SOAP_SNPRINTF(soap->msgbuf + l, sizeof(soap->msgbuf) - l, 40), " (%d%csec max send delay)", st, su);
22559  }
22560 #endif
22561  }
22562  }
22563  return soap->msgbuf;
22564 }
22565 #endif
22566 
22567 /******************************************************************************/
22568 
22569 static int
22570 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
22571 {
22572  *soap_faultcode(soap) = faultcode;
22573  if (faultsubcodeQName)
22574  *soap_faultsubcode(soap) = faultsubcodeQName;
22575  *soap_faultstring(soap) = faultstring;
22576  if (faultdetailXML && *faultdetailXML)
22577  {
22578  const char **s = soap_faultdetail(soap);
22579  if (s)
22580  *s = faultdetailXML;
22581  }
22582  return soap->error = soaperror;
22583 }
22584 
22585 /******************************************************************************/
22586 
22587 SOAP_FMAC1
22588 int
22589 SOAP_FMAC2
22590 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
22591 {
22592  return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client" : "at sender", NULL, faultstring, faultdetailXML, soaperror);
22593 }
22594 
22595 /******************************************************************************/
22596 
22597 SOAP_FMAC1
22598 int
22599 SOAP_FMAC2
22600 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
22601 {
22602  return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server" : "detected", NULL, faultstring, faultdetailXML, soaperror);
22603 }
22604 
22605 /******************************************************************************/
22606 
22607 static int
22608 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
22609 {
22610  char *r = NULL, *s = NULL, *t = NULL;
22611  DBGFUN2("soap_copy_fault", "code=%s", faultcode ? faultcode : "(null)", "string=%s", faultstring ? faultstring : "(null)")
22612  if (faultsubcodeQName)
22613  r = soap_strdup(soap, faultsubcodeQName);
22614  if (faultstring)
22615  s = soap_strdup(soap, faultstring);
22616  if (faultdetailXML)
22617  t = soap_strdup(soap, faultdetailXML);
22618  return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
22619 }
22620 
22621 /******************************************************************************/
22622 
22623 SOAP_FMAC1
22624 int
22625 SOAP_FMAC2
22626 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
22627 {
22628  return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
22629 }
22630 
22631 /******************************************************************************/
22632 
22633 SOAP_FMAC1
22634 int
22635 SOAP_FMAC2
22636 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
22637 {
22638  return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : soap->version == 1 ? "SOAP-ENV:Client" : "at source", faultsubcodeQName, faultstring, faultdetailXML);
22639 }
22640 
22641 /******************************************************************************/
22642 
22643 SOAP_FMAC1
22644 int
22645 SOAP_FMAC2
22646 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
22647 {
22648  return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
22649 }
22650 
22651 /******************************************************************************/
22652 
22653 SOAP_FMAC1
22654 int
22655 SOAP_FMAC2
22656 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
22657 {
22658  return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : soap->version == 1 ? "SOAP-ENV:Server" : "is internal", faultsubcodeQName, faultstring, faultdetailXML);
22659 }
22660 
22661 /******************************************************************************/
22662 
22663 #ifndef WITH_NOSTDLIB
22664 SOAP_FMAC1
22665 void
22666 SOAP_FMAC2
22667 soap_print_fault(struct soap *soap, FILE *fd)
22668 {
22669  if (soap_check_state(soap))
22670  {
22671  fprintf(fd, "Error: soap struct state not initialized\n");
22672  }
22673  else if (soap->error)
22674  {
22675  const char **c, *v = NULL, *s, *d;
22676  c = soap_faultcode(soap);
22677  if (!*c)
22678  {
22680  c = soap_faultcode(soap);
22681  }
22682  if (soap->version == 2)
22683  v = soap_fault_subcode(soap);
22684  s = soap_fault_string(soap);
22686  fprintf(fd, "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
22687  }
22688 }
22689 #endif
22690 
22691 /******************************************************************************/
22692 
22693 #ifdef __cplusplus
22694 #ifndef WITH_LEAN
22695 #ifndef WITH_NOSTDLIB
22696 #ifndef WITH_COMPAT
22697 SOAP_FMAC1
22698 void
22699 SOAP_FMAC2
22700 soap_stream_fault(struct soap *soap, std::ostream& os)
22701 {
22702  if (soap_check_state(soap))
22703  {
22704  os << "Error: soap struct state not initialized\n";
22705  }
22706  else if (soap->error)
22707  {
22708  const char **c, *v = NULL, *s, *d;
22709  c = soap_faultcode(soap);
22710  if (!*c)
22711  {
22713  c = soap_faultcode(soap);
22714  }
22715  if (soap->version == 2)
22716  v = soap_fault_subcode(soap);
22717  s = soap_fault_string(soap);
22719  os << (soap->version ? "SOAP 1." : "Error ")
22720  << (soap->version ? (int)soap->version : soap->error)
22721  << " fault " << *c
22722  << "[" << (v ? v : "no subcode") << "]"
22723  << std::endl
22724  << "\"" << (s ? s : "[no reason]") << "\""
22725  << std::endl
22726  << "Detail: " << (d ? d : "[no detail]")
22727  << std::endl;
22728  }
22729 }
22730 #endif
22731 #endif
22732 #endif
22733 #endif
22734 
22735 /******************************************************************************/
22736 
22737 #ifndef WITH_LEAN
22738 #ifndef WITH_NOSTDLIB
22739 SOAP_FMAC1
22740 char*
22741 SOAP_FMAC2
22742 soap_sprint_fault(struct soap *soap, char *buf, size_t len)
22743 {
22744  if (soap_check_state(soap))
22745  {
22746  soap_strcpy(buf, len, "Error: soap struct not initialized");
22747  }
22748  else if (soap->error)
22749  {
22750  const char **c, *v = NULL, *s, *d;
22751  c = soap_faultcode(soap);
22752  if (!*c)
22753  {
22755  c = soap_faultcode(soap);
22756  }
22757  if (soap->version == 2)
22758  v = soap_fault_subcode(soap);
22759  if (!v)
22760  v = "no subcode";
22761  s = soap_fault_string(soap);
22762  if (!s)
22763  s = "[no reason]";
22765  if (!d)
22766  d = "[no detail]";
22767  (SOAP_SNPRINTF(buf, len, strlen(*c) + strlen(v) + strlen(s) + strlen(d) + 72), "%s%d fault %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v, s, d);
22768  }
22769  else if (len > 0)
22770  {
22771  *buf = '\0';
22772  }
22773  return buf;
22774 }
22775 #endif
22776 #endif
22777 
22778 /******************************************************************************/
22779 
22780 #ifndef WITH_NOSTDLIB
22781 SOAP_FMAC1
22782 void
22783 SOAP_FMAC2
22785 {
22786 #ifndef WITH_LEAN
22787  int i, j, c1, c2;
22788  if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= sizeof(soap->buf))
22789  {
22790  i = (int)soap->bufidx - 1;
22791  if (i <= 0)
22792  i = 0;
22793  c1 = soap->buf[i];
22794  soap->buf[i] = '\0';
22795  if ((int)soap->buflen >= i + 1024)
22796  j = i + 1023;
22797  else
22798  j = (int)soap->buflen - 1;
22799  c2 = soap->buf[j];
22800  soap->buf[j] = '\0';
22801  fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
22802  if (soap->bufidx < soap->buflen)
22803  fprintf(fd, "%s\n", soap->buf + soap->bufidx);
22804  soap->buf[i] = (char)c1;
22805  soap->buf[j] = (char)c2;
22806  }
22807 #else
22808  (void)soap;
22809  (void)fd;
22810 #endif
22811 }
22812 #endif
22813 
22814 /******************************************************************************/
22815 
22816 #ifdef __cplusplus
22817 #ifndef WITH_LEAN
22818 #ifndef WITH_NOSTDLIB
22819 #ifndef WITH_COMPAT
22820 SOAP_FMAC1
22821 void
22822 SOAP_FMAC2
22823 soap_stream_fault_location(struct soap *soap, std::ostream& os)
22824 {
22825  int i, j, c1, c2;
22826  if (soap_check_state(soap) == SOAP_OK && soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= sizeof(soap->buf))
22827  {
22828  i = (int)soap->bufidx - 1;
22829  if (i <= 0)
22830  i = 0;
22831  c1 = soap->buf[i];
22832  soap->buf[i] = '\0';
22833  if ((int)soap->buflen >= i + 1024)
22834  j = i + 1023;
22835  else
22836  j = (int)soap->buflen - 1;
22837  c2 = soap->buf[j];
22838  soap->buf[j] = '\0';
22839  os << soap->buf << (char)c1 << std::endl << "<!-- ** HERE ** -->" << std::endl;
22840  if (soap->bufidx < soap->buflen)
22841  os << soap->buf + soap->bufidx << std::endl;
22842  soap->buf[i] = (char)c1;
22843  soap->buf[j] = (char)c2;
22844  }
22845 }
22846 #endif
22847 #endif
22848 #endif
22849 #endif
22850 
22851 /******************************************************************************/
22852 
22853 SOAP_FMAC1
22854 int
22855 SOAP_FMAC2
22856 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
22857 {
22858  struct soap_plugin *p;
22859  int err;
22860  p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin));
22861  if (!p)
22862  return soap->error = SOAP_EOM;
22863  p->id = NULL;
22864  p->data = NULL;
22865  p->fcopy = NULL;
22866  p->fdelete = NULL;
22867  err = fcreate(soap, p, arg);
22868  if (!err && p->fdelete && p->id)
22869  {
22870  if (!soap_lookup_plugin(soap, p->id))
22871  {
22872  p->next = soap->plugins;
22873  soap->plugins = p;
22874  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
22875  return SOAP_OK;
22876  }
22877  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin with the same ID already registered\n", p->id));
22878  SOAP_FREE(soap, p);
22879  return SOAP_OK;
22880  }
22881  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d or plugin ID not set or fdelete callback not set\n", p->id ? p->id : "plugin ID not set", err));
22882  SOAP_FREE(soap, p);
22883  soap->error = err ? err : SOAP_PLUGIN_ERROR;
22884  return soap->error;
22885 }
22886 
22887 /******************************************************************************/
22888 
22889 static void *
22890 fplugin(struct soap *soap, const char *id)
22891 {
22892  struct soap_plugin *p;
22893  for (p = soap->plugins; p; p = p->next)
22894  if (p->id == id || !strcmp(p->id, id))
22895  return p->data;
22896  return NULL;
22897 }
22898 
22899 /******************************************************************************/
22900 
22901 SOAP_FMAC1
22902 void *
22903 SOAP_FMAC2
22904 soap_lookup_plugin(struct soap *soap, const char *id)
22905 {
22906  return soap->fplugin(soap, id);
22907 }
22908 
22909 /******************************************************************************/
22910 
22911 #ifdef __cplusplus
22912 }
22913 #endif
22914 
22915 /******************************************************************************\
22916  *
22917  * C++ soap struct methods
22918  *
22919 \******************************************************************************/
22920 
22921 #ifdef __cplusplus
22922 soap::soap()
22923 {
22924  soap_init(this);
22925  /* no logs to prevent DEBUG mode leaks when the user calls a soap_init() on this context */
22926  soap_set_test_logfile(this, NULL);
22927  soap_set_sent_logfile(this, NULL);
22928  soap_set_recv_logfile(this, NULL);
22929 }
22930 #endif
22931 
22932 /******************************************************************************/
22933 
22934 #ifdef __cplusplus
22936 {
22937  soap_init1(this, m);
22938 }
22939 #endif
22940 
22941 /******************************************************************************/
22942 
22943 #ifdef __cplusplus
22945 {
22946  soap_init2(this, im, om);
22947 }
22948 #endif
22949 
22950 /******************************************************************************/
22951 
22952 #ifdef __cplusplus
22953 soap::soap(const struct soap& soap)
22954 {
22955  soap_copy_context(this, &soap);
22956 }
22957 #endif
22958 
22959 /******************************************************************************/
22960 
22961 #ifdef __cplusplus
22962 struct soap& soap::operator=(const struct soap& soap)
22963 {
22964  soap_done(this);
22965  soap_copy_context(this, &soap);
22966  return *this;
22967 }
22968 #endif
22969 
22970 /******************************************************************************/
22971 
22972 #ifdef __cplusplus
22973 void soap::destroy()
22974 {
22975  soap_destroy(this);
22976  soap_end(this);
22977 }
22978 #endif
22979 
22980 /******************************************************************************/
22981 
22982 #ifdef __cplusplus
22983 soap::~soap()
22984 {
22985  soap_done(this);
22986 }
22987 #endif
22988 
22989 /******************************************************************************/
CHARSET_INFO fields description
NAME if(";${DISABLED_AC_MODULES};" MATCHES ";${MODULENAME};") continue() endif() if(EXISTS "$
Definition: CMakeLists.txt:68
fno inline small functions fno default inline endif() message("Unit tests code coverage
Definition: CMakeLists.txt:151
lib set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1) set(AC_PATH_ROOT "$
Definition: CMakeLists.txt:32
TEST(FormulasTest, hk_honor_at_level)
G3D::Matrix abs(const G3D::Matrix &M)
Definition: Matrix.h:632
int next(int i, int n)
static uint pos(unsigned char c)
Definition: base64.c:104
FMT_MODULE_EXPORT_BEGIN std::tm localtime(std::time_t time)
Definition: chrono.h:368
std::tm gmtime(std::time_t time)
Definition: chrono.h:414
FMT_BEGIN_DETAIL_NAMESPACE size_t strftime(char *str, size_t count, const char *format, const std::tm *time)
Definition: chrono.h:456
size_t chunksize
Definition: chunk.c:27
Definition: core.h:1120
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
Definition: color.h:583
int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength)
Definition: deflate.c:323
int ZEXPORT deflateEnd(z_streamp strm)
Definition: deflate.c:977
int ZEXPORT deflate(z_streamp strm, int flush)
Definition: deflate.c:663
static Bigint * diff(Bigint *a, Bigint *b, Stack_alloc *alloc)
Definition: dtoa.c:1108
#define d1
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1725
constexpr auto count() -> size_t
Definition: core.h:1039
type
Definition: core.h:1048
auto ptr(T p) -> const void *
Definition: format.h:2451
#define read
Definition: hooks.h:10
#define close
Definition: hooks.h:13
#define write
Definition: hooks.h:11
int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength)
Definition: inflate.c:1267
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:604
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1253
arena_t NULL
#define memset(A, C, B)
Definition: m_string.h:51
#define min(a, b)
Definition: my_global.h:1387
#define LL(A)
Definition: my_global.h:1001
#define max(a, b)
Definition: my_global.h:1386
struct tm * localtime_r(const time_t *clock, struct tm *res)
Definition: my_pthread.c:75
ulong crc32(ulong crc, const uchar *buf, uint len)
G3D::int16 z
Definition: Vector3int16.h:46
uint16 bits() const
Returns the underlying bits in this representation. Equivalent to:
Definition: unorm16.h:89
G3D::int16 x
Definition: Vector2int16.h:37
float length(float v)
Definition: vectorMath.h:208
Vector2int16 & operator=(const Any &a)
const T & first(const T &value, const Tail &...)
Definition: compile.h:178
null gmtime_r(...)
Definition: chrono.h:288
OutputIterator copy(const RangeT &range, OutputIterator out)
Definition: ranges.h:50
extern(C)
Definition: mpq.d:53
file
Definition: mpq.py:283
d
Definition: mpq.py:298
l
Definition: mpq.py:297
a
Definition: mpq.py:290
list c
Definition: mpq.py:295
version
Definition: setup.py:15
auto fprintf(std::FILE *f, const S &fmt, const T &... args) -> int
Definition: printf.h:602
int ret
Definition: prof.c:281
const prof_gctx_t * b
Definition: prof.c:277
SOAP_FMAC3 const char **SOAP_FMAC4 soap_faultsubcode(struct soap *soap)
Definition: soapC.cpp:100
SOAP_FMAC3 int SOAP_FMAC4 soap_getheader(struct soap *soap)
Definition: soapC.cpp:26
SOAP_FMAC3 void SOAP_FMAC4 soap_serializefault(struct soap *soap)
Definition: soapC.cpp:72
SOAP_FMAC3 const char **SOAP_FMAC4 soap_faultcode(struct soap *soap)
Definition: soapC.cpp:90
SOAP_FMAC3 void SOAP_FMAC4 soap_serializeheader(struct soap *soap)
Definition: soapC.cpp:45
SOAP_FMAC3 const char *SOAP_FMAC4 soap_fault_string(struct soap *soap)
Definition: soapC.cpp:132
SOAP_FMAC3 const char *SOAP_FMAC4 soap_fault_subcode(struct soap *soap)
Definition: soapC.cpp:116
SOAP_FMAC3 const char **SOAP_FMAC4 soap_faultdetail(struct soap *soap)
Definition: soapC.cpp:138
SOAP_FMAC3 int SOAP_FMAC4 soap_putfault(struct soap *soap)
Definition: soapC.cpp:78
SOAP_FMAC3 const char **SOAP_FMAC4 soap_faultstring(struct soap *soap)
Definition: soapC.cpp:122
SOAP_FMAC3 const char *SOAP_FMAC4 soap_fault_detail(struct soap *soap)
Definition: soapC.cpp:153
SOAP_FMAC3 int SOAP_FMAC4 soap_getfault(struct soap *soap)
Definition: soapC.cpp:85
SOAP_FMAC3 int SOAP_FMAC4 soap_putheader(struct soap *soap)
Definition: soapC.cpp:34
int f(int *a)
SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
Definition: stdsoap2.cpp:17295
SOAP_FMAC1 char *SOAP_FMAC2 soap_strdup(struct soap *soap, const char *s)
Definition: stdsoap2.cpp:2789
SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap *soap, const char *s, short *p)
Definition: stdsoap2.cpp:16495
SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap *soap)
Definition: stdsoap2.cpp:22446
SOAP_FMAC1 int SOAP_FMAC2 soap_GET(struct soap *soap, const char *endpoint, const char *action)
Definition: stdsoap2.cpp:21249
SOAP_FMAC1 int SOAP_FMAC2 soap_match_att(struct soap *soap, const char *tag1, const char *tag2)
Definition: stdsoap2.cpp:3847
static int soap_begin_attachments(struct soap *)
Definition: stdsoap2.cpp:20137
SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
Definition: stdsoap2.cpp:12513
SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap *soap, struct soap_blist *b)
Definition: stdsoap2.cpp:3283
SOAP_FMAC1 int SOAP_FMAC2 soap_binary_search_string(const char **a, int n, const char *s)
Definition: stdsoap2.cpp:1873
SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
Definition: stdsoap2.cpp:19974
static SOAP_SOCKET tcp_accept(struct soap *, SOAP_SOCKET, struct sockaddr *, int *)
Definition: stdsoap2.cpp:6567
SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap *soap, const char *logfile)
Definition: stdsoap2.cpp:11677
SOAP_FMAC1 char *SOAP_FMAC2 soap_http_get_body_prefix(struct soap *soap, size_t *len, const char *prefix)
Definition: stdsoap2.cpp:20915
SOAP_FMAC1 double *SOAP_FMAC2 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
Definition: stdsoap2.cpp:16887
SOAP_FMAC1 const char *SOAP_FMAC2 soap_ULONG642s(struct soap *soap, ULONG64 n)
Definition: stdsoap2.cpp:17284
static void soap_free_iht(struct soap *)
Definition: stdsoap2.cpp:10324
SOAP_FMAC1 const char *SOAP_FMAC2 soap_unsignedInt2s(struct soap *soap, unsigned int n)
Definition: stdsoap2.cpp:17087
SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
Definition: stdsoap2.cpp:13340
SOAP_FMAC1 const char *SOAP_FMAC2 soap_float2s(struct soap *soap, float n)
Definition: stdsoap2.cpp:16556
static soap_wchar soap_getchunkchar(struct soap *)
Definition: stdsoap2.cpp:1326
static int soap_isxdigit(int)
Definition: stdsoap2.cpp:1343
SOAP_FMAC1 int SOAP_FMAC2 soap_begin_serve(struct soap *soap)
Definition: stdsoap2.cpp:20414
SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap *soap, const char *endpoint, const char *action)
Definition: stdsoap2.cpp:21329
SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap *soap)
Definition: stdsoap2.cpp:20109
SOAP_FMAC1 long *SOAP_FMAC2 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
Definition: stdsoap2.cpp:16247
SOAP_FMAC1 void *SOAP_FMAC2 soap_push_block_max(struct soap *soap, struct soap_blist *b, size_t n)
Definition: stdsoap2.cpp:2943
static int soap_set_error(struct soap *, const char *, const char *, const char *, const char *, int)
Definition: stdsoap2.cpp:22570
SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap *soap, const char *s, size_t n)
Definition: stdsoap2.cpp:14383
SOAP_FMAC1 struct soap_clist *SOAP_FMAC2 soap_link(struct soap *soap, int t, int n, int(*fdelete)(struct soap *, struct soap_clist *))
Definition: stdsoap2.cpp:10768
static size_t frecv(struct soap *, char *, size_t)
Definition: stdsoap2.cpp:1128
static const char * soap_strerror(struct soap *)
Definition: stdsoap2.cpp:22477
SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap *soap, const char *s, double *p)
Definition: stdsoap2.cpp:16817
SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap *soap, const void *p, int t)
Definition: stdsoap2.cpp:10031
SOAP_FMAC1 const char *SOAP_FMAC2 soap_long2s(struct soap *soap, long n)
Definition: stdsoap2.cpp:16193
SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const *p, const char *type)
Definition: stdsoap2.cpp:18923
SOAP_FMAC1 char *SOAP_FMAC2 soap_http_get_body(struct soap *soap, size_t *len)
Definition: stdsoap2.cpp:20895
#define SOAP_QT
Definition: stdsoap2.cpp:111
SOAP_FMAC1 int SOAP_FMAC2 soap_http_skip_body(struct soap *soap)
Definition: stdsoap2.cpp:20857
#define SOAP_SOCKNONBLOCK(fd)
Definition: stdsoap2.cpp:320
SOAP_FMAC1 float *SOAP_FMAC2 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
Definition: stdsoap2.cpp:16734
SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap *soap, const char *tag, int id, char *const *p, const char *type, int n)
Definition: stdsoap2.cpp:18281
SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap *soap, const char *s, size_t n)
Definition: stdsoap2.cpp:916
SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap)
Definition: stdsoap2.cpp:14212
static const char soap_enc2[40]
Definition: stdsoap2.cpp:328
SOAP_FMAC1 wchar_t **SOAP_FMAC2 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
Definition: stdsoap2.cpp:18950
SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
Definition: stdsoap2.cpp:2469
SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
Definition: stdsoap2.cpp:17209
static void soap_free_ns(struct soap *)
Definition: stdsoap2.cpp:11568
SOAP_FMAC1 LONG64 SOAP_FMAC2 soap_code_bits(const struct soap_code_map *code_map, const char *str)
Definition: stdsoap2.cpp:1812
SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
Definition: stdsoap2.cpp:2713
SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap *soap, int(*fcreate)(struct soap *, struct soap_plugin *, void *), void *arg)
Definition: stdsoap2.cpp:22856
SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap *soap, const char *s, size_t n)
Definition: stdsoap2.cpp:825
SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap *soap, struct soap_blist *b)
Definition: stdsoap2.cpp:2958
SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap *soap, const char *s, int flag)
Definition: stdsoap2.cpp:15054
SOAP_FMAC1 unsigned short *SOAP_FMAC2 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
Definition: stdsoap2.cpp:17047
SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap *soap)
Definition: stdsoap2.cpp:1595
SOAP_FMAC1 int SOAP_FMAC2 soap_http_has_body(struct soap *soap)
Definition: stdsoap2.cpp:20847
SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap *soap, FILE *fd)
Definition: stdsoap2.cpp:22784
#define SOAP_TT
Definition: stdsoap2.cpp:109
SOAP_FMAC1 void SOAP_FMAC2 soap_mark_dup(struct soap *soap, void *a, struct soap_plist *pp)
Definition: stdsoap2.cpp:13771
SOAP_FMAC1 unsigned char *SOAP_FMAC2 soap_gethex(struct soap *soap, int *n)
Definition: stdsoap2.cpp:2339
SOAP_FMAC1 struct soap_multipart *SOAP_FMAC2 soap_recv_mime_attachment(struct soap *soap, void *handle)
Definition: stdsoap2.cpp:19700
static int soap_putdimefield(struct soap *, const char *, size_t)
Definition: stdsoap2.cpp:19162
static void soap_free_pht(struct soap *)
Definition: stdsoap2.cpp:9605
SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap *soap)
Definition: stdsoap2.cpp:14986
SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap *soap, const char *endpoint)
Definition: stdsoap2.cpp:21139
SOAP_FMAC1 void SOAP_FMAC2 soap_unmark(struct soap *soap, char *mark)
Definition: stdsoap2.cpp:13783
SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap *soap, void *p)
Definition: stdsoap2.cpp:10635
static void soap_version(struct soap *)
Definition: stdsoap2.cpp:12476
SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
Definition: stdsoap2.cpp:18671
SOAP_FMAC1 const char *SOAP_FMAC2 soap_extend_url_query(struct soap *soap, const char *s, const char *t)
Definition: stdsoap2.cpp:8463
SOAP_FMAC1 const char *SOAP_FMAC2 soap_unsignedLong2s(struct soap *soap, unsigned long n)
Definition: stdsoap2.cpp:17185
SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
Definition: stdsoap2.cpp:13889
SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:17521
SOAP_FMAC1 int SOAP_FMAC2 soap_id_nullify(struct soap *soap, const char *id)
Definition: stdsoap2.cpp:11182
SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
Definition: stdsoap2.cpp:18686
static int tcp_init(struct soap *)
Definition: stdsoap2.cpp:5015
static soap_wchar soap_getpi(struct soap *)
Definition: stdsoap2.cpp:2083
SOAP_FMAC1 short SOAP_FMAC2 soap_begin_shaky(struct soap *soap)
Definition: stdsoap2.cpp:10862
static int soap_has_copies(struct soap *, const char *, const char *)
Definition: stdsoap2.cpp:3061
SOAP_FMAC1 void *SOAP_FMAC2 soap_malloc(struct soap *soap, size_t n)
Definition: stdsoap2.cpp:10401
SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap *soap)
Definition: stdsoap2.cpp:21093
static int http_get(struct soap *)
Definition: stdsoap2.cpp:7971
SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap *soap)
Definition: stdsoap2.cpp:14975
static void * fplugin(struct soap *, const char *)
Definition: stdsoap2.cpp:22890
SOAP_FMAC1 struct soap_nlist *SOAP_FMAC2 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
Definition: stdsoap2.cpp:12644
SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap *soap, const char *s, size_t n)
Definition: stdsoap2.cpp:14396
SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char *s)
Definition: stdsoap2.cpp:9539
SOAP_FMAC1 int SOAP_FMAC2 soap_check_and_mark(struct soap *soap, const void *p, int t, char **mark)
Definition: stdsoap2.cpp:13693
SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap *soap)
Definition: stdsoap2.cpp:9824
SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_accept(struct soap *soap)
Definition: stdsoap2.cpp:7009
SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap *soap, const char *logfile)
Definition: stdsoap2.cpp:11690
SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap *soap)
Definition: stdsoap2.cpp:12402
SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap *soap, const char *s, long *p)
Definition: stdsoap2.cpp:16217
SOAP_FMAC1 size_t SOAP_FMAC2 soap_utf8len(const char *s)
Definition: stdsoap2.cpp:2289
SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap *soap)
Definition: stdsoap2.cpp:867
SOAP_FMAC1 time_t *SOAP_FMAC2 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
Definition: stdsoap2.cpp:18822
SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
Definition: stdsoap2.cpp:22626
SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap *soap, const char *type)
Definition: stdsoap2.cpp:3894
SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap *soap)
Definition: stdsoap2.cpp:19660
SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_bind(struct soap *soap, const char *host, int port, int backlog)
Definition: stdsoap2.cpp:6719
SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap *soap)
Definition: stdsoap2.cpp:11209
SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap *soap, const char *tag, int id, const char *type)
Definition: stdsoap2.cpp:12763
#define SOAP_LT
Definition: stdsoap2.cpp:108
#define SOAP_UNKNOWN_CHAR
Definition: stdsoap2.cpp:97
static int soap_valid_mime_boundary(struct soap *)
Definition: stdsoap2.cpp:20332
SOAP_FMAC1 const char *SOAP_FMAC2 soap_encode_url_string(struct soap *soap, const char *s)
Definition: stdsoap2.cpp:8554
SOAP_FMAC1 int SOAP_FMAC2 soap_check_mime_attachments(struct soap *soap)
Definition: stdsoap2.cpp:19686
SOAP_FMAC1 void *SOAP_FMAC2 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
Definition: stdsoap2.cpp:2910
SOAP_FMAC1 short *SOAP_FMAC2 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
Definition: stdsoap2.cpp:16516
SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap *soap)
Definition: stdsoap2.cpp:9996
SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap *soap)
Definition: stdsoap2.cpp:3089
static const char soap_indent[21]
Definition: stdsoap2.cpp:336
static int http_response(struct soap *, int, ULONG64)
Definition: stdsoap2.cpp:8259
static const struct soap_code_map h_http_error_codes[]
Definition: stdsoap2.cpp:480
SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap *soap, const char *logfile)
Definition: stdsoap2.cpp:11664
SOAP_FMAC1 void SOAP_FMAC2 soap_end_shaky(struct soap *soap, short f)
Definition: stdsoap2.cpp:10876
SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13795
SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap *soap)
Definition: stdsoap2.cpp:2220
SOAP_FMAC1 char *SOAP_FMAC2 soap_query(struct soap *soap)
Definition: stdsoap2.cpp:1026
SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char *s, const char *t)
Definition: stdsoap2.cpp:3723
SOAP_FMAC1 const char *SOAP_FMAC2 soap_tagsearch(const char *big, const char *little)
Definition: stdsoap2.cpp:12610
SOAP_FMAC1 int SOAP_FMAC2 soap_unlink(struct soap *soap, const void *p)
Definition: stdsoap2.cpp:10800
SOAP_FMAC1 int SOAP_FMAC2 soap_PUT(struct soap *soap, const char *endpoint, const char *action, const char *type)
Definition: stdsoap2.cpp:21261
#define SOAP_TCP_SELECT_ALL
Definition: stdsoap2.cpp:271
SOAP_FMAC1 const char *SOAP_FMAC2 soap_http_content_type(struct soap *soap, int status)
Definition: stdsoap2.cpp:21794
SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
Definition: stdsoap2.cpp:16104
#define SOAP_SOCKBLOCK(fd)
Definition: stdsoap2.cpp:319
SOAP_FMAC1 void *SOAP_FMAC2 soap_memdup(struct soap *soap, const void *s, size_t n)
Definition: stdsoap2.cpp:2772
static int soap_isnumeric(struct soap *, const char *)
Definition: stdsoap2.cpp:16701
static struct soap_multipart * soap_alloc_multipart(struct soap *, struct soap_multipart **, struct soap_multipart **, const char *, size_t)
Definition: stdsoap2.cpp:20214
SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
Definition: stdsoap2.cpp:17196
SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
Definition: stdsoap2.cpp:16399
SOAP_FMAC1 size_t SOAP_FMAC2 soap_getsizes(const char *attr, int *size, int dim)
Definition: stdsoap2.cpp:3456
SOAP_FMAC1 ULONG64 SOAP_FMAC2 soap_tell(struct soap *soap)
Definition: stdsoap2.cpp:2146
SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap *soap, const char *tag, char *const *p, const char *type)
Definition: stdsoap2.cpp:18858
SOAP_FMAC1 void SOAP_FMAC2 soap_strcat(char *t, size_t n, const char *s)
Definition: stdsoap2.cpp:13033
static const char * soap_string(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:17418
SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const void *a, int n, int t)
Definition: stdsoap2.cpp:9627
SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
Definition: stdsoap2.cpp:16299
SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap *soap, int httpstatuscode)
Definition: stdsoap2.cpp:22423
SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap *soap, const char *name, const char *value)
Definition: stdsoap2.cpp:13829
SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
Definition: stdsoap2.cpp:16943
SOAP_FMAC1 struct soap_ilist *SOAP_FMAC2 soap_lookup(struct soap *soap, const char *id)
Definition: stdsoap2.cpp:10353
static const struct soap_code_map h_error_codes[]
Definition: stdsoap2.cpp:456
SOAP_FMAC1 void *SOAP_FMAC2 soap_mark_lookup(struct soap *soap, const void *p, int t, struct soap_plist **ppp, char **mark)
Definition: stdsoap2.cpp:13725
const char soap_base64i[81]
Definition: stdsoap2.cpp:333
SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap *soap)
Definition: stdsoap2.cpp:3604
#define SOAP_GT
Definition: stdsoap2.cpp:110
SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_out(struct soap *soap)
Definition: stdsoap2.cpp:20831
#define SOAP_STR_EOS
Definition: stdsoap2.cpp:348
SOAP_FMAC1 void *SOAP_FMAC2 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k, int(*fbase)(int, int))
Definition: stdsoap2.cpp:10902
static const wchar_t * soap_wstring(struct soap *soap, const char *s, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:17931
SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap *soap)
Definition: stdsoap2.cpp:7280
SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
Definition: stdsoap2.cpp:16930
#define soap_coblank(c)
Definition: stdsoap2.cpp:114
SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
Definition: stdsoap2.cpp:17097
SOAP_FMAC1 const struct soap_code_map *SOAP_FMAC2 soap_code(const struct soap_code_map *code_map, const char *str)
Definition: stdsoap2.cpp:1760
SOAP_FMAC1 const char *SOAP_FMAC2 soap_int2s(struct soap *soap, int n)
Definition: stdsoap2.cpp:16094
SOAP_FMAC1 const char *SOAP_FMAC2 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
Definition: stdsoap2.cpp:1844
SOAP_FMAC1 int SOAP_FMAC2 soap_end_send_flush(struct soap *soap)
Definition: stdsoap2.cpp:11243
SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
Definition: stdsoap2.cpp:17026
SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
Definition: stdsoap2.cpp:3776
SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap *soap)
Definition: stdsoap2.cpp:19391
SOAP_FMAC1 const char *SOAP_FMAC2 soap_current_namespace_att(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:3694
SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap *soap)
Definition: stdsoap2.cpp:6907
SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *aid, const char *atype, const char *aoptions, const char *type, int t)
Definition: stdsoap2.cpp:10217
SOAP_FMAC1 ULONG64 *SOAP_FMAC2 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
Definition: stdsoap2.cpp:17340
#define SOAP_TCP_SELECT_PIP
Definition: stdsoap2.cpp:272
SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
Definition: stdsoap2.cpp:16312
static void soap_init_pht(struct soap *)
Definition: stdsoap2.cpp:9550
SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(const struct soap *soap)
Definition: stdsoap2.cpp:11703
static const char soap_env1[42]
Definition: stdsoap2.cpp:325
SOAP_FMAC1 const char *SOAP_FMAC2 soap_double2s(struct soap *soap, double n)
Definition: stdsoap2.cpp:16767
SOAP_FMAC1 LONG64 SOAP_FMAC2 soap_code_int(const struct soap_code_map *code_map, const char *str, LONG64 other)
Definition: stdsoap2.cpp:1779
static int soap_getattrval(struct soap *, char *, size_t *, soap_wchar)
Definition: stdsoap2.cpp:14238
SOAP_FMAC1 char *SOAP_FMAC2 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
Definition: stdsoap2.cpp:21586
SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
Definition: stdsoap2.cpp:22636
SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap *soap, const char *s, char *p)
Definition: stdsoap2.cpp:16412
SOAP_FMAC1 const char *SOAP_FMAC2 soap_code_str(const struct soap_code_map *code_map, long code)
Definition: stdsoap2.cpp:1798
static int tcp_disconnect(struct soap *)
Definition: stdsoap2.cpp:6589
SOAP_FMAC1 const char *SOAP_FMAC2 soap_dateTime2s(struct soap *soap, time_t n)
Definition: stdsoap2.cpp:18561
SOAP_FMAC1 time_t SOAP_FMAC2 soap_timegm(struct tm *T)
Definition: stdsoap2.cpp:18523
SOAP_FMAC1 wchar_t *SOAP_FMAC2 soap_wstrtrim(struct soap *soap, wchar_t *s)
Definition: stdsoap2.cpp:2864
static void soap_resolve_attachment(struct soap *, struct soap_multipart *)
Definition: stdsoap2.cpp:19937
#define SOAP_CANARY
Definition: stdsoap2.cpp:343
static const char soap_padding[4]
Definition: stdsoap2.cpp:346
SOAP_FMAC1 int *SOAP_FMAC2 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
Definition: stdsoap2.cpp:16152
SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap *soap)
Definition: stdsoap2.cpp:20123
static const struct soap_code_map mime_codes[]
Definition: stdsoap2.cpp:549
SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap *soap, FILE *fd)
Definition: stdsoap2.cpp:22667
SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap *soap)
Definition: stdsoap2.cpp:1959
SOAP_FMAC1 void *SOAP_FMAC2 soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, const char *type, const char *arrayType, void *(*finstantiate)(struct soap *, int, const char *, const char *, size_t *), int(*fbase)(int, int))
Definition: stdsoap2.cpp:11054
static int soap_type_punned(struct soap *, const struct soap_ilist *)
Definition: stdsoap2.cpp:11163
SOAP_FMAC1 char *SOAP_FMAC2 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:15157
SOAP_FMAC1 int SOAP_FMAC2 soap_encode_url(const char *s, char *t, int len)
Definition: stdsoap2.cpp:8513
SOAP_FMAC1 const char *SOAP_FMAC2 soap_value(struct soap *soap)
Definition: stdsoap2.cpp:19002
static soap_wchar soap_char(struct soap *)
Definition: stdsoap2.cpp:1893
SOAP_FMAC1 LONG64 *SOAP_FMAC2 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
Definition: stdsoap2.cpp:16342
SOAP_FMAC1 char *SOAP_FMAC2 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
Definition: stdsoap2.cpp:19176
SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *attr, int *pos)
Definition: stdsoap2.cpp:3512
SOAP_FMAC1 char *SOAP_FMAC2 soap_http_get_form(struct soap *soap)
Definition: stdsoap2.cpp:20905
SOAP_FMAC1 int SOAP_FMAC2 soap_POST(struct soap *soap, const char *endpoint, const char *action, const char *type)
Definition: stdsoap2.cpp:21279
#define soap_hash_ptr(p)
Definition: stdsoap2.cpp:119
SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap *soap, int check)
Definition: stdsoap2.cpp:22324
SOAP_FMAC1 struct soap_multipart *SOAP_FMAC2 soap_next_multipart(struct soap_multipart *content)
Definition: stdsoap2.cpp:20284
SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
Definition: stdsoap2.cpp:17013
static int tcp_select(struct soap *, SOAP_SOCKET, int, int)
Definition: stdsoap2.cpp:6366
#define SOAP_TCP_SELECT_ERR
Definition: stdsoap2.cpp:270
SOAP_FMAC1 void SOAP_FMAC2 soap_url_query(struct soap *soap, const char *s, const char *t)
Definition: stdsoap2.cpp:8478
SOAP_FMAC1 void SOAP_FMAC2 soap_del(struct soap *soap)
Definition: stdsoap2.cpp:9597
SOAP_FMAC1 const char *SOAP_FMAC2 soap_unsignedShort2s(struct soap *soap, unsigned short n)
Definition: stdsoap2.cpp:17003
SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const *p, const char *type, int n)
Definition: stdsoap2.cpp:18359
SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
Definition: stdsoap2.cpp:9654
SOAP_FMAC1 int SOAP_FMAC2 soap_element_nil(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13634
SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
Definition: stdsoap2.cpp:3481
SOAP_FMAC1 int SOAP_FMAC2 soap_PATCH(struct soap *soap, const char *endpoint, const char *action, const char *type)
Definition: stdsoap2.cpp:21297
SOAP_FMAC1 void SOAP_FMAC2 soap_initialize(struct soap *soap)
Definition: stdsoap2.cpp:12040
SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap *soap)
Definition: stdsoap2.cpp:9744
static int http_patch(struct soap *)
Definition: stdsoap2.cpp:7994
static int http_post(struct soap *, const char *, const char *, int, const char *, const char *, ULONG64)
Definition: stdsoap2.cpp:8030
SOAP_FMAC1 size_t SOAP_FMAC2 soap_size(const int *size, int dim)
Definition: stdsoap2.cpp:3435
SOAP_FMAC1 void SOAP_FMAC2 soap_copy_stream(struct soap *copy, struct soap *soap)
Definition: stdsoap2.cpp:11828
#define SOAP_STR_PADDING
Definition: stdsoap2.cpp:347
SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
Definition: stdsoap2.cpp:16482
SOAP_FMAC1 void SOAP_FMAC2 soap_update_pointers(struct soap *soap, const char *dst, const char *src, size_t len)
Definition: stdsoap2.cpp:2978
static int tcp_gethostbyname(struct soap *, const char *addr, struct hostent *hostent, struct in_addr *inaddr)
Definition: stdsoap2.cpp:5069
#define SOAP_AP
Definition: stdsoap2.cpp:112
SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap *soap)
Definition: stdsoap2.cpp:9582
static const char * tcp_error(struct soap *)
Definition: stdsoap2.cpp:5037
SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap *soap)
Definition: stdsoap2.cpp:20447
SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
Definition: stdsoap2.cpp:3621
SOAP_FMAC1 struct soap_ilist *SOAP_FMAC2 soap_enter(struct soap *soap, const char *id, int t, size_t n)
Definition: stdsoap2.cpp:10369
SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap *soap, unsigned long c)
Definition: stdsoap2.cpp:2157
SOAP_FMAC1 char *SOAP_FMAC2 soap_query_key(struct soap *soap, char **s)
Definition: stdsoap2.cpp:1038
static void soap_select_mime_boundary(struct soap *)
Definition: stdsoap2.cpp:20296
SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap *soap, struct soap_blist *b)
Definition: stdsoap2.cpp:3295
static ULONG64 soap_count_attachments(struct soap *)
Definition: stdsoap2.cpp:19098
SOAP_FMAC1 void SOAP_FMAC2 soap_free_temp(struct soap *soap)
Definition: stdsoap2.cpp:11513
SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap *soap, const char *s1, const char *s2)
Definition: stdsoap2.cpp:962
SOAP_FMAC1 const char *SOAP_FMAC2 soap_extend_url(struct soap *soap, const char *s, const char *t)
Definition: stdsoap2.cpp:8425
SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
Definition: stdsoap2.cpp:976
SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap *soap)
Definition: stdsoap2.cpp:19439
SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13384
SOAP_FMAC1 const char *SOAP_FMAC2 soap_decode_val(char *buf, size_t len, const char *val)
Definition: stdsoap2.cpp:7895
SOAP_FMAC1 char **SOAP_FMAC2 soap_inliteral(struct soap *soap, const char *tag, char **p)
Definition: stdsoap2.cpp:18876
SOAP_FMAC1 char **SOAP_FMAC2 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:18300
SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
Definition: stdsoap2.cpp:17110
SOAP_FMAC1 char *SOAP_FMAC2 soap_strtrim(struct soap *soap, char *s)
Definition: stdsoap2.cpp:2841
SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap *soap)
Definition: stdsoap2.cpp:21078
SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap *soap)
Definition: stdsoap2.cpp:21015
const char soap_base64o[65]
Definition: stdsoap2.cpp:332
SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap *soap, const char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
Definition: stdsoap2.cpp:20246
static int fsend(struct soap *, const char *, size_t)
Definition: stdsoap2.cpp:576
static const char * soap_set_validation_fault(struct soap *, const char *, const char *)
Definition: stdsoap2.cpp:21948
SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap *soap, struct soap_plist *pp)
Definition: stdsoap2.cpp:10182
SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap *soap, const void *p, const void *a, int n, int t)
Definition: stdsoap2.cpp:10059
static int tcp_closesocket(struct soap *, SOAP_SOCKET)
Definition: stdsoap2.cpp:6693
static struct soap_nlist * soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized, short isearly)
Definition: stdsoap2.cpp:12657
static int http_put(struct soap *)
Definition: stdsoap2.cpp:7983
SOAP_FMAC1 char *SOAP_FMAC2 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
Definition: stdsoap2.cpp:21722
static const char * http_error(struct soap *, int)
Definition: stdsoap2.cpp:7953
SOAP_FMAC1 struct soap_nlist *SOAP_FMAC2 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
Definition: stdsoap2.cpp:3535
static int soap_init_send(struct soap *)
Definition: stdsoap2.cpp:9844
SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
Definition: stdsoap2.cpp:22590
SOAP_FMAC1 char *SOAP_FMAC2 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
Definition: stdsoap2.cpp:16433
SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const void *a, int n, const char *type, int t, char **mark)
Definition: stdsoap2.cpp:13647
static int http_post_header(struct soap *, const char *, const char *)
Definition: stdsoap2.cpp:8242
SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap *soap, const char *s, int *p)
Definition: stdsoap2.cpp:16117
SOAP_FMAC1 void *SOAP_FMAC2 soap_lookup_plugin(struct soap *soap, const char *id)
Definition: stdsoap2.cpp:22904
SOAP_FMAC1 char *SOAP_FMAC2 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
Definition: stdsoap2.cpp:3342
SOAP_FMAC1 wchar_t **SOAP_FMAC2 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:18380
static const char soap_env2[40]
Definition: stdsoap2.cpp:327
SOAP_FMAC1 int SOAP_FMAC2 soap_strncat(char *t, size_t n, const char *s, size_t m)
Definition: stdsoap2.cpp:13054
static const struct soap_code_map html_entity_codes[]
Definition: stdsoap2.cpp:352
SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap *soap, const char *s, float *p)
Definition: stdsoap2.cpp:16606
#define SOAP_NON_NULL
Definition: stdsoap2.cpp:349
SOAP_FMAC1 int SOAP_FMAC2 soap_attachment_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
Definition: stdsoap2.cpp:2742
SOAP_FMAC1 int SOAP_FMAC2 soap_query_send_key(struct soap *soap, const char *s)
Definition: stdsoap2.cpp:991
SOAP_FMAC1 void SOAP_FMAC2 soap_free_stream(struct soap *soap)
Definition: stdsoap2.cpp:12006
static char * soap_getdimefield(struct soap *, size_t)
Definition: stdsoap2.cpp:19350
SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap *soap, const unsigned char *s, int n)
Definition: stdsoap2.cpp:2303
SOAP_FMAC1 void *SOAP_FMAC2 soap_id_forward(struct soap *soap, const char *href, void *p, size_t i, int t, int tt, size_t n, unsigned int k, void(*finsert)(struct soap *, int, int, void *, size_t, const void *, void **), int(*fbase)(int, int))
Definition: stdsoap2.cpp:10990
static int http_parse(struct soap *)
Definition: stdsoap2.cpp:7501
SOAP_FMAC1 const char *SOAP_FMAC2 soap_rand_uuid(struct soap *soap, const char *prefix)
Definition: stdsoap2.cpp:19897
static void soap_init_iht(struct soap *)
Definition: stdsoap2.cpp:10312
static const char * soap_QName(struct soap *soap, const char *s, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:17557
SOAP_FMAC1 const char *SOAP_FMAC2 soap_http_header_attribute(struct soap *soap, const char *line, const char *key)
Definition: stdsoap2.cpp:7858
SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap *soap)
Definition: stdsoap2.cpp:21046
SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap *soap, ULONG64 n)
Definition: stdsoap2.cpp:2130
SOAP_FMAC1 char *SOAP_FMAC2 soap_next_block(struct soap *soap, struct soap_blist *b)
Definition: stdsoap2.cpp:3261
SOAP_FMAC1 int SOAP_FMAC2 soap_s2char(struct soap *soap, const char *s, char **t, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:17384
SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp)
Definition: stdsoap2.cpp:9720
SOAP_FMAC1 void SOAP_FMAC2 soap_post_check_mime_attachments(struct soap *soap)
Definition: stdsoap2.cpp:19674
SOAP_FMAC1 const char *SOAP_FMAC2 soap_byte2s(struct soap *soap, char n)
Definition: stdsoap2.cpp:16389
SOAP_FMAC1 unsigned long *SOAP_FMAC2 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
Definition: stdsoap2.cpp:17243
SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap *soap, int status)
Definition: stdsoap2.cpp:8383
SOAP_FMAC1 const char *SOAP_FMAC2 soap_wchar2s(struct soap *soap, const wchar_t *s)
Definition: stdsoap2.cpp:18183
static const char soap_rpc[35]
Definition: stdsoap2.cpp:329
SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap *soap)
Definition: stdsoap2.cpp:20001
SOAP_FMAC1 unsigned char *SOAP_FMAC2 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
Definition: stdsoap2.cpp:16964
static int tcp_shutdownsocket(struct soap *, SOAP_SOCKET, int)
Definition: stdsoap2.cpp:6705
SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap *soap, char *buf, int len)
Definition: stdsoap2.cpp:19054
SOAP_FMAC1 wchar_t *SOAP_FMAC2 soap_wstrdup(struct soap *soap, const wchar_t *s)
Definition: stdsoap2.cpp:2813
SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
Definition: stdsoap2.cpp:16804
SOAP_FMAC1 const char *SOAP_FMAC2 soap_decode_key(char *buf, size_t len, const char *val)
Definition: stdsoap2.cpp:7883
SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap *soap)
Definition: stdsoap2.cpp:20818
SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap *soap, const char *s)
Definition: stdsoap2.cpp:949
SOAP_FMAC1 void SOAP_FMAC2 soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
Definition: stdsoap2.cpp:10689
SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap *soap)
Definition: stdsoap2.cpp:1353
SOAP_FMAC1 const char *SOAP_FMAC2 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
Definition: stdsoap2.cpp:21750
SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap *soap)
Definition: stdsoap2.cpp:22226
SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
Definition: stdsoap2.cpp:22646
static int http_del(struct soap *)
Definition: stdsoap2.cpp:8004
SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap *soap)
Definition: stdsoap2.cpp:11393
SOAP_FMAC1 const char *SOAP_FMAC2 soap_unsignedByte2s(struct soap *soap, unsigned char n)
Definition: stdsoap2.cpp:16920
SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap *soap, const char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
Definition: stdsoap2.cpp:20264
SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
Definition: stdsoap2.cpp:21339
SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap *soap, const void *p, const void *a, int n, int type, struct soap_plist **ppp)
Definition: stdsoap2.cpp:9679
SOAP_FMAC1 const char *SOAP_FMAC2 soap_query_decode(char *buf, size_t len, const char *val)
Definition: stdsoap2.cpp:1076
static int http_parse_header(struct soap *, const char *, const char *)
Definition: stdsoap2.cpp:7668
SOAP_FMAC1 wchar_t *SOAP_FMAC2 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:15899
SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
Definition: stdsoap2.cpp:13578
SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
Definition: stdsoap2.cpp:10159
static int http_200(struct soap *)
Definition: stdsoap2.cpp:8014
SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
Definition: stdsoap2.cpp:13013
SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap *soap, const char *id)
Definition: stdsoap2.cpp:10839
SOAP_FMAC1 char *SOAP_FMAC2 soap_query_val(struct soap *soap, char **s)
Definition: stdsoap2.cpp:1057
SOAP_FMAC1 char *SOAP_FMAC2 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
Definition: stdsoap2.cpp:3378
SOAP_FMAC1 int SOAP_FMAC2 soap_element_end(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13515
SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
Definition: stdsoap2.cpp:13556
SOAP_FMAC1 const char *SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag, int occurs)
Definition: stdsoap2.cpp:14033
static const char * soap_decode(char *, size_t, const char *, const char *)
Definition: stdsoap2.cpp:7910
SOAP_FMAC1 const char *SOAP_FMAC2 soap_LONG642s(struct soap *soap, LONG64 n)
Definition: stdsoap2.cpp:16288
SOAP_FMAC1 const char *SOAP_FMAC2 soap_short2s(struct soap *soap, short n)
Definition: stdsoap2.cpp:16472
SOAP_FMAC1 const char *SOAP_FMAC2 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
Definition: stdsoap2.cpp:21630
SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap *soap)
Definition: stdsoap2.cpp:19586
static wchar_t * soap_wcollapse(struct soap *soap, wchar_t *s, int flag, int insitu)
Definition: stdsoap2.cpp:18110
SOAP_FMAC1 int SOAP_FMAC2 soap_match_cid(struct soap *soap, const char *s, const char *t)
Definition: stdsoap2.cpp:19867
#define SOAP_TCP_SELECT_SND
Definition: stdsoap2.cpp:269
SOAP_FMAC1 void SOAP_FMAC2 soap_versioning() soap_init(struct soap *soap, soap_mode imode, soap_mode omode)
Definition: stdsoap2.cpp:12050
SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
Definition: stdsoap2.cpp:22656
SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap *soap, int status, ULONG64 count)
Definition: stdsoap2.cpp:21878
SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap *soap)
Definition: stdsoap2.cpp:21125
SOAP_FMAC1 void SOAP_FMAC2 soap_set_version(struct soap *soap, short version)
Definition: stdsoap2.cpp:12450
SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
Definition: stdsoap2.cpp:14068
SOAP_FMAC1 int SOAP_FMAC2 soap_mark_cycle(struct soap *soap, struct soap_plist *pp)
Definition: stdsoap2.cpp:13760
SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
Definition: stdsoap2.cpp:13594
SOAP_FMAC1 char *SOAP_FMAC2 soap_putoffsets(struct soap *soap, const int *offset, int dim)
Definition: stdsoap2.cpp:3413
static int soap_is_shaky(struct soap *, void *)
Definition: stdsoap2.cpp:10886
SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap *soap)
Definition: stdsoap2.cpp:7263
static int soap_end_attachments(struct soap *soap)
Definition: stdsoap2.cpp:20182
SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap *soap)
Definition: stdsoap2.cpp:12576
SOAP_FMAC1 unsigned int *SOAP_FMAC2 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
Definition: stdsoap2.cpp:17144
SOAP_FMAC1 int SOAP_FMAC2 soap_DELETE(struct soap *soap, const char *endpoint)
Definition: stdsoap2.cpp:21315
SOAP_FMAC1 int SOAP_FMAC2 soap_query_send_val(struct soap *soap, const char *s)
Definition: stdsoap2.cpp:1009
SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap *soap)
Definition: stdsoap2.cpp:21965
SOAP_FMAC1 int SOAP_FMAC2 soap_force_closesock(struct soap *soap)
Definition: stdsoap2.cpp:7233
SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
Definition: stdsoap2.cpp:17308
SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap *soap)
Definition: stdsoap2.cpp:12427
SOAP_FMAC1 const char *SOAP_FMAC2 soap_QName2s(struct soap *soap, const char *s)
Definition: stdsoap2.cpp:17752
SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
Definition: stdsoap2.cpp:16593
SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap *soap)
Definition: stdsoap2.cpp:21110
SOAP_FMAC1 int SOAP_FMAC2 soap_ignore(struct soap *soap)
Definition: stdsoap2.cpp:15002
SOAP_FMAC1 int SOAP_FMAC2 soap_ready(struct soap *soap)
Definition: stdsoap2.cpp:6968
static int soap_copy_fault(struct soap *, const char *, const char *, const char *, const char *)
Definition: stdsoap2.cpp:22608
SOAP_FMAC1 struct soap_blist *SOAP_FMAC2 soap_alloc_block(struct soap *soap)
Definition: stdsoap2.cpp:2887
SOAP_FMAC1 char *SOAP_FMAC2 soap_first_block(struct soap *soap, struct soap_blist *b)
Definition: stdsoap2.cpp:3235
SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
Definition: stdsoap2.cpp:10117
SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
Definition: stdsoap2.cpp:16204
SOAP_FMAC1 void SOAP_FMAC2 soap_check_result(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13814
SOAP_FMAC1 char *SOAP_FMAC2 soap_sprint_fault(struct soap *soap, char *buf, size_t len)
Definition: stdsoap2.cpp:22742
#define SOAP_TCP_SELECT_RCV
Definition: stdsoap2.cpp:268
SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
Definition: stdsoap2.cpp:3218
SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap *soap)
Definition: stdsoap2.cpp:1742
SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap *soap, void *p)
Definition: stdsoap2.cpp:10560
static SOAP_SOCKET tcp_connect(struct soap *, const char *endpoint, const char *host, int port)
Definition: stdsoap2.cpp:5191
SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap *soap, const void *p, int t)
Definition: stdsoap2.cpp:10013
SOAP_FMAC1 const char *SOAP_FMAC2 soap_current_namespace_tag(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:3650
SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap *soap)
Definition: stdsoap2.cpp:19249
SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap *copy, const struct soap *soap)
Definition: stdsoap2.cpp:11721
SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap *soap)
Definition: stdsoap2.cpp:7191
static void soap_utilize_ns(struct soap *soap, const char *tag, short isearly)
Definition: stdsoap2.cpp:12722
SOAP_FMAC1 int SOAP_FMAC2 soap_element_empty(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13622
SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
Definition: stdsoap2.cpp:15810
SOAP_FMAC1 int SOAP_FMAC2 soap_attachment_reference(struct soap *soap, const void *p, const void *a, int n, int t, const char *id, const char *type)
Definition: stdsoap2.cpp:10087
static char * soap_collapse(struct soap *soap, char *s, int flag, int insitu)
Definition: stdsoap2.cpp:17456
SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13927
SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
Definition: stdsoap2.cpp:22600
SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap *soap)
Definition: stdsoap2.cpp:19203
SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap *soap)
Definition: stdsoap2.cpp:20079
SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap *soap)
Definition: stdsoap2.cpp:14442
static const char soap_enc1[42]
Definition: stdsoap2.cpp:326
static int soap_try_connect_command(struct soap *, int http_command, const char *endpoint, const char *action)
Definition: stdsoap2.cpp:21397
static int http_send_header(struct soap *, const char *)
Definition: stdsoap2.cpp:8222
SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap *soap)
Definition: stdsoap2.cpp:21059
static int tcp_gethost(struct soap *, const char *addr, struct in_addr *inaddr)
Definition: stdsoap2.cpp:5179
SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
Definition: stdsoap2.cpp:10200
SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap *soap, const char *tag)
Definition: stdsoap2.cpp:13499
SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, int flag, long minlen, long maxlen, const char *pattern)
Definition: stdsoap2.cpp:17893
SOAP_FMAC1 void **SOAP_FMAC2 soap_id_smart(struct soap *soap, const char *id, int t, size_t n)
Definition: stdsoap2.cpp:11139
SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_versioning() soap_new(soap_mode imode, soap_mode omode)
Definition: stdsoap2.cpp:9564
SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
Definition: stdsoap2.cpp:20093
SOAP_FMAC1 unsigned char *SOAP_FMAC2 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
Definition: stdsoap2.cpp:2523
#define SOAP_IN_ENVELOPE
Definition: stdsoap2.h:1779
#define SOAP_FORM
Definition: stdsoap2.h:1651
#define SOAP_C_NILSTRING
Definition: stdsoap2.h:1727
#define SOAP_BINARY_BUFLEN
Definition: stdsoap2.h:631
#define SOAP_FILE
Definition: stdsoap2.h:1653
#define soap_strncpy(buf, len, src, num)
Definition: stdsoap2.h:1499
#define SOAP_IO_KEEPALIVE
Definition: stdsoap2.h:1697
#define SOAP_XML_INDENT
Definition: stdsoap2.h:1710
#define SOAP_MOE
Definition: stdsoap2.h:1549
SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap *)
#define SOAP_SSLv3
Definition: stdsoap2.h:1752
#define SOAP_PATCH
Definition: stdsoap2.h:1663
SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_crl(struct soap *, const char *)
#define SOAP_DEL_METHOD
Definition: stdsoap2.h:1546
#define SOAP_ERR
Definition: stdsoap2.h:1582
#define SOAP_DIME_MB
Definition: stdsoap2.h:1673
#define SOAP_INDEX_SENT
Definition: stdsoap2.h:1245
#define FLT_NINFTY
Definition: stdsoap2.h:1408
struct SOAP_CMAC soap
Definition: stdsoap2.h:1997
#define SOAP_DATAENCODINGUNKNOWN
Definition: stdsoap2.h:1569
#define SOAP_CHK_EOF
Definition: stdsoap2.h:1012
#define SOAP_HTML
Definition: stdsoap2.h:1652
soap_int32 soap_wchar
Definition: stdsoap2.h:1994
#define FLT_NAN
Definition: stdsoap2.h:1388
#define SOAP_SSL_NO_DEFAULT_CA_PATH
Definition: stdsoap2.h:1750
#define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2)
Definition: stdsoap2.h:1987
#define SOAP_SHUT_WR
Definition: stdsoap2.h:998
#define soap_memmove(buf, len, src, num)
Definition: stdsoap2.h:1520
#define SOAP_EMPTY
Definition: stdsoap2.h:1580
#define soap_unget(soap, c)
Definition: stdsoap2.h:3059
#define SOAP_EOF
Definition: stdsoap2.h:1527
#define SOAP_DUPLICATE_ID
Definition: stdsoap2.h:1552
#define SOAP_ZLIB_DEFLATE
Definition: stdsoap2.h:1681
#define DBGMSG(DBGFILE, MSG, LEN)
Definition: stdsoap2.h:1984
#define soap_init1(soap, mode)
Definition: stdsoap2.h:3051
#define SOAP_HDRLEN
Definition: stdsoap2.h:1211
SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile)
#define SOAP_MAXARRAYSIZE
Definition: stdsoap2.h:1276
#define SOAP_IO_DEFAULT
Definition: stdsoap2.h:1740
#define SOAP_SSL_ERROR
Definition: stdsoap2.h:1558
#define SOAP_MAXLEVEL
Definition: stdsoap2.h:1313
#define SOAP_DIME_MISMATCH
Definition: stdsoap2.h:1562
#define SOAP_EWOULDBLOCK
Definition: stdsoap2.h:1141
#define SOAP_SSL_SKIP_HOST_CHECK
Definition: stdsoap2.h:1748
#define SOAP_NONE
Definition: stdsoap2.h:1768
#define SOAP_IN_BODY
Definition: stdsoap2.h:1783
SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_noinit(void)
#define SOAP_HEAD
Definition: stdsoap2.h:1665
#define SOAP_ECONNREFUSED
Definition: stdsoap2.h:1136
#define SOAP_BEGIN_SEND
Definition: stdsoap2.h:1777
#define SOAP_PUT
Definition: stdsoap2.h:1662
#define soap_versioning(name)
Definition: stdsoap2.h:3048
#define soap_ispinff(n)
Definition: stdsoap2.h:1452
#define SOAP_MAXDIMS
Definition: stdsoap2.h:1225
#define SOAP_IO_UDP
Definition: stdsoap2.h:1695
#define SOAP_MAXOCCURS
Definition: stdsoap2.h:1323
#define SOAP_XML_NOTYPE
Definition: stdsoap2.h:1716
#define SOAP_GET
Definition: stdsoap2.h:1661
#define SOAP_OK
Definition: stdsoap2.h:1528
#define DBL_NAN
Definition: stdsoap2.h:1412
#define SOAP_NO_TAG
Definition: stdsoap2.h:1534
#define SOAP_FUNC_R_ERR
Definition: stdsoap2.h:982
#define SOAP_BLKLEN
Definition: stdsoap2.h:1197
soap_mime_encoding
Definition: stdsoap2.h:2177
@ SOAP_MIME_8BIT
Definition: stdsoap2.h:2180
@ SOAP_MIME_QUOTED_PRINTABLE
Definition: stdsoap2.h:2182
@ SOAP_MIME_IETF_TOKEN
Definition: stdsoap2.h:2184
@ SOAP_MIME_BASE64
Definition: stdsoap2.h:2183
@ SOAP_MIME_NONE
Definition: stdsoap2.h:2178
@ SOAP_MIME_BINARY
Definition: stdsoap2.h:2181
@ SOAP_MIME_X_TOKEN
Definition: stdsoap2.h:2185
@ SOAP_MIME_7BIT
Definition: stdsoap2.h:2179
#define SOAP_EAGAIN
Definition: stdsoap2.h:1134
#define SOAP_POST
Definition: stdsoap2.h:1659
#define SOAP_END
Definition: stdsoap2.h:1776
#define SOAP_MAXINFLATESIZE
Definition: stdsoap2.h:1294
SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init(void)
#define soap_valid_socket(sk)
Definition: stdsoap2.h:996
SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap *, const char *, int, void *)
#define DBL_NINFTY
Definition: stdsoap2.h:1432
#define SOAP_VERSIONMISMATCH
Definition: stdsoap2.h:1567
#define SOAP_XML_NIL
Definition: stdsoap2.h:1715
#define SOAP_MIME_ERROR
Definition: stdsoap2.h:1564
#define SOAP_WINSOCKINT
Definition: stdsoap2.h:838
#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
Definition: stdsoap2.h:1747
#define SOAP_IOB
Definition: stdsoap2.h:1535
#define SOAP_POST_FILE
Definition: stdsoap2.h:1660
#define DBGLOG(DBGFILE, CMD)
Definition: stdsoap2.h:1983
#define SOAP_DOM_ASIS
Definition: stdsoap2.h:1720
#define SOAP_TCP_ERROR
Definition: stdsoap2.h:1556
#define SOAP_EINTR
Definition: stdsoap2.h:1133
#define SOAP_FD_EXCEEDED
Definition: stdsoap2.h:1575
#define SOAP_SYNTAX_ERROR
Definition: stdsoap2.h:1533
#define SOAP_SSL_CLIENT
Definition: stdsoap2.h:1760
#define soap_memcpy(buf, len, src, num)
Definition: stdsoap2.h:1513
#define SOAP_OCCURS
Definition: stdsoap2.h:1572
#define SOAP_INDEX_RECV
Definition: stdsoap2.h:1244
#define soap_strcpy(buf, len, src)
Definition: stdsoap2.h:1483
#define soap_revget1(soap)
Definition: stdsoap2.h:3058
#define SOAP_DIME_ME
Definition: stdsoap2.h:1672
#define soap_strtol(s, t, b)
Definition: stdsoap2.h:3082
#define SOAP_MAXEINTR
Definition: stdsoap2.h:1262
#define SOAP_ENC_LATIN
Definition: stdsoap2.h:1700
#define SOAP_ZLIB_NONE
Definition: stdsoap2.h:1680
#define SOAP_FMAC2
Definition: stdsoap2.h:109
#define SOAP_PROHIBITED
Definition: stdsoap2.h:1571
#define SOAP_XML_STRICT
Definition: stdsoap2.h:1709
#define SOAP_MINDEFLATERATIO
Definition: stdsoap2.h:1308
SOAP_NMAC struct Namespace namespaces[]
Definition: ACSoap.cpp:142
#define SOAP_SSL_DEFAULT
Definition: stdsoap2.h:1762
SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
#define DBL_PINFTY
Definition: stdsoap2.h:1427
#define SOAP_SNPRINTF(buf, len, num)
Definition: stdsoap2.h:1469
#define SOAP_INDEX_TEST
Definition: stdsoap2.h:1246
#define SOAP_DELETE_UNMANAGED(soap)
Definition: stdsoap2.h:1893
#define SOAP_UDP_ERROR
Definition: stdsoap2.h:1555
#define soap_isninfd(n)
Definition: stdsoap2.h:1453
#define SOAP_IO_BUFFER
Definition: stdsoap2.h:1691
SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap *, int)
#define SOAP_HREF
Definition: stdsoap2.h:1554
#define SOAP_DEL
Definition: stdsoap2.h:1664
#define SOAP_MUSTUNDERSTAND
Definition: stdsoap2.h:1536
#define SOAP_SOCKET
Definition: stdsoap2.h:990
#define SOAP_BUFLEN
Definition: stdsoap2.h:1170
#define SOAP_INIT
Definition: stdsoap2.h:1769
#define SOAP_BASEREFNAME
Definition: stdsoap2.h:1256
#define SOAP_NEW_UNMANAGED(soap)
Definition: stdsoap2.h:1889
#define SOAP_XSTRINGIFY(s)
Definition: stdsoap2.h:151
#define SOAP_END_TAG
Definition: stdsoap2.h:1581
#define SOAP_XML_CANONICAL
Definition: stdsoap2.h:1713
#define SOAP_UTF_ERROR
Definition: stdsoap2.h:1576
#define SOAP_NULL
Definition: stdsoap2.h:1551
#define soap_isnan(n)
Definition: stdsoap2.h:1439
#define SOAP_END_ENVELOPE
Definition: stdsoap2.h:1785
#define SOAP_HDR
Definition: stdsoap2.h:1550
#define LONG64
Definition: stdsoap2.h:1085
#define DBGHEX(DBGFILE, MSG, LEN)
Definition: stdsoap2.h:1990
#define SOAP_MISSING_ID
Definition: stdsoap2.h:1553
#define soap_destroy(soap)
Definition: stdsoap2.h:3071
#define soap_errno
Definition: stdsoap2.h:1158
#define SOAP_NAMESPACE
Definition: stdsoap2.h:1537
#define ULONG64
Definition: stdsoap2.h:1086
#define SOAP_HTTP_METHOD
Definition: stdsoap2.h:1547
#define SOAP_TAG_MISMATCH
Definition: stdsoap2.h:1531
#define soap_closesocket(n)
Definition: stdsoap2.h:991
#define SOAP_SEC_BEGIN
Definition: stdsoap2.h:1789
#define FD_SETSIZE
Definition: stdsoap2.h:1006
#define SOAP_STRCMP
Definition: stdsoap2.h:944
#define FLT_PINFTY
Definition: stdsoap2.h:1403
#define SOAP_ULONG_FORMAT
Definition: stdsoap2.h:1102
#define soap_reset_errno
Definition: stdsoap2.h:1160
#define SOAP_IDHASH
Definition: stdsoap2.h:1190
#define SOAP_XML_IGNORENS
Definition: stdsoap2.h:1711
#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
Definition: stdsoap2.h:1746
#define SOAP_C_UTFSTRING
Definition: stdsoap2.h:1725
#define SOAP_DIME_MEDIA
Definition: stdsoap2.h:1675
#define SOAP_SOCKLEN_T
Definition: stdsoap2.h:971
#define SOAP_CLI_FAULT
Definition: stdsoap2.h:1529
#define SOAP_PLUGIN_ERROR
Definition: stdsoap2.h:1568
#define SOAP_LEVEL
Definition: stdsoap2.h:1578
#define SOAP_MAXKEEPALIVE
Definition: stdsoap2.h:1267
#define SOAP_ENC
Definition: stdsoap2.h:1699
#define SOAP_NO_DATA
Definition: stdsoap2.h:1542
#define SOAP_MALLOC_UNMANAGED(size)
Definition: stdsoap2.h:1828
#define SOAP_ENC_MIME
Definition: stdsoap2.h:1704
soap_int32 soap_mode
Definition: stdsoap2.h:1687
#define SOAP_ERANGE
Definition: stdsoap2.h:1131
#define SOAP_XML_CANONICAL_NA
Definition: stdsoap2.h:1722
#define SOAP_PTRBLK
Definition: stdsoap2.h:1179
SOAP_FMAC1 const char *SOAP_FMAC2 soap_ssl_error(struct soap *, int ret, int err)
#define SOAP_MAXPTRS
Definition: stdsoap2.h:1232
#define SOAP_ZLIB_INFLATE
Definition: stdsoap2.h:1682
#define SOAP_FIXED
Definition: stdsoap2.h:1579
#define SOAP_MIME_END
Definition: stdsoap2.h:1566
#define soap_get1(soap)
Definition: stdsoap2.h:3040
#define SOAP_EOM
Definition: stdsoap2.h:1548
#define SOAP_STOP
Definition: stdsoap2.h:1650
#define SOAP_ZLIB_ERROR
Definition: stdsoap2.h:1559
#define SOAP_XML_TREE
Definition: stdsoap2.h:1714
#define SOAP_DIME_VERSION
Definition: stdsoap2.h:1674
SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap *)
#define SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
Definition: stdsoap2.h:1749
#define SOAP_ENC_PLAIN
Definition: stdsoap2.h:1701
#define SOAP_COPY
Definition: stdsoap2.h:1770
#define SOAP_DIME_HREF
Definition: stdsoap2.h:1561
SOAP_FMAC1 void *SOAP_FMAC2 soap_track_malloc(struct soap *, const char *, int, size_t)
#define SOAP_XML_DEFAULTNS
Definition: stdsoap2.h:1712
#define SOAP_LABLEN
Definition: stdsoap2.h:1176
#define soap_strtoll
Definition: stdsoap2.h:3096
#define SOAP_FREE_UNMANAGED(ptr)
Definition: stdsoap2.h:1832
#define SOAP_TLSv1_2
Definition: stdsoap2.h:1755
#define SOAP_CONNECT
Definition: stdsoap2.h:1667
#define soap_init2(soap, imode, omode)
Definition: stdsoap2.h:3052
#define SOAP_NO_METHOD
Definition: stdsoap2.h:1541
#define soap_isninff(n)
Definition: stdsoap2.h:1454
#define SOAP_SVR_FAULT
Definition: stdsoap2.h:1530
#define soap_int32
Definition: stdsoap2.h:1116
#define SOAP_SSL_RSA
Definition: stdsoap2.h:1751
#define SOAP_TLSv1_1
Definition: stdsoap2.h:1754
#define SOAP_OPTIONS
Definition: stdsoap2.h:1666
#define soap_strtoull
Definition: stdsoap2.h:3104
#define SOAP_INVALID_SOCKET
Definition: stdsoap2.h:995
#define SOAP_MAXLENGTH
Definition: stdsoap2.h:1318
#define SOAP_LONG_FORMAT
Definition: stdsoap2.h:1098
#define SOAP_IO_FLUSH
Definition: stdsoap2.h:1690
#define SOAP_TLSv1
Definition: stdsoap2.h:1757
#define SOAP_C_MBSTRING
Definition: stdsoap2.h:1726
#define SOAP_BEGIN_RECV
Definition: stdsoap2.h:1778
#define soap_random
Definition: stdsoap2.h:3117
#define SOAP_TLSv1_0
Definition: stdsoap2.h:1753
#define SOAP_SOURCE_STAMP(str)
Definition: stdsoap2.h:145
#define SOAP_ENC_MTOM
Definition: stdsoap2.h:1705
#define SOAP_DIME_CF
Definition: stdsoap2.h:1671
#define SOAP_GET_METHOD
Definition: stdsoap2.h:1543
#define SOAP_DIME_ERROR
Definition: stdsoap2.h:1560
#define SOAP_NO_BODY
Definition: stdsoap2.h:1782
#define SOAP_USER_ERROR
Definition: stdsoap2.h:1538
#define SOAP_HTTP_ERROR
Definition: stdsoap2.h:1557
#define soap_socket_errno
Definition: stdsoap2.h:1159
#define soap_check_state(soap)
Definition: stdsoap2.h:1772
#define SOAP_MAXDIMESIZE
Definition: stdsoap2.h:1285
#define soap_strrchr(s, t)
Definition: stdsoap2.h:3076
#define SOAP_SHUT_RDWR
Definition: stdsoap2.h:999
#define SOAP_GAI_STRERROR
Definition: stdsoap2.h:1002
#define SOAP_PUT_METHOD
Definition: stdsoap2.h:1544
#define SOAP_LENGTH
Definition: stdsoap2.h:1573
#define SOAP_DIME_ABSURI
Definition: stdsoap2.h:1676
#define SOAP_MIME_POSTCHECK
Definition: stdsoap2.h:1732
#define SOAP_NO_LINK_TO_DELETE
Definition: stdsoap2.h:3073
#define SOAP_ZLIB_GZIP
Definition: stdsoap2.h:1683
#define SOAP_SNPRINTF_SAFE(buf, len)
Definition: stdsoap2.h:1470
#define SOAP_MALLOC(soap, size)
Definition: stdsoap2.h:1820
#define SOAP_IO_LENGTH
Definition: stdsoap2.h:1696
#define SOAP_PTRHASH
Definition: stdsoap2.h:1183
#define SOAP_NTLM_ERROR
Definition: stdsoap2.h:1577
#define SOAP_IO
Definition: stdsoap2.h:1689
#define soap_ispinfd(n)
Definition: stdsoap2.h:1451
#define SOAP_ENC_SSL
Definition: stdsoap2.h:1707
#define SOAP_IN_HEADER
Definition: stdsoap2.h:1780
#define SOAP_MIME_HREF
Definition: stdsoap2.h:1565
#define soap_get0(soap)
Definition: stdsoap2.h:3039
#define SOAP_IO_CHUNK
Definition: stdsoap2.h:1693
#define SOAP_EADDRINUSE
Definition: stdsoap2.h:1135
#define SOAP_REQUIRED
Definition: stdsoap2.h:1570
#define SOAP_TLSv1_3
Definition: stdsoap2.h:1756
#define SOAP_SEC_WSUID
Definition: stdsoap2.h:1734
#define SOAP_DIME_END
Definition: stdsoap2.h:1563
#define soap_peek(soap)
Definition: stdsoap2.h:3060
#define SOAP_XML_DOM
Definition: stdsoap2.h:1729
#define SOAP_FREE(soap, ptr)
Definition: stdsoap2.h:1824
#define SOAP_SSLv3_TLSv1
Definition: stdsoap2.h:1758
#define SOAP_FAULT
Definition: stdsoap2.h:1540
#define soap_strtoul(s, t, b)
Definition: stdsoap2.h:3088
#define SOAP_XML_GRAPH
Definition: stdsoap2.h:1730
#define SOAP_END_BODY
Definition: stdsoap2.h:1784
#define SOAP_IO_STORE
Definition: stdsoap2.h:1692
#define SOAP_PATCH_METHOD
Definition: stdsoap2.h:1545
#define SOAP_FMAC1
Definition: stdsoap2.h:105
#define SOAP_ENC_ZLIB
Definition: stdsoap2.h:1706
#define SOAP_ENC_DIME
Definition: stdsoap2.h:1703
#define SOAP_MAXALLOCSIZE
Definition: stdsoap2.h:1239
#define SOAP_TYPE
Definition: stdsoap2.h:1532
#define SOAP_MAXLOGS
Definition: stdsoap2.h:1243
#define SOAP_EINPROGRESS
Definition: stdsoap2.h:1142
const char * in
Definition: stdsoap2.h:2004
char * out
Definition: stdsoap2.h:2005
const char * ns
Definition: stdsoap2.h:2003
const char * id
Definition: stdsoap2.h:2002
Definition: inftrees.h:24
Definition: format.h:897
const char * ns
Definition: stdsoap2.h:2084
char name[1]
Definition: stdsoap2.h:2086
struct soap_attribute * next
Definition: stdsoap2.h:2080
char * value
Definition: stdsoap2.h:2082
struct soap_bhead * next
Definition: stdsoap2.h:2021
size_t size
Definition: stdsoap2.h:2022
size_t item
Definition: stdsoap2.h:2031
struct soap_blist * next
Definition: stdsoap2.h:2028
size_t size
Definition: stdsoap2.h:2030
struct soap_bhead * head
Definition: stdsoap2.h:2029
void * ptr
Definition: stdsoap2.h:2071
struct soap_clist * next
Definition: stdsoap2.h:2070
int(* fdelete)(struct soap *, struct soap_clist *)
Definition: stdsoap2.h:2074
LONG64 code
Definition: stdsoap2.h:2996
const char * string
Definition: stdsoap2.h:2997
struct soap_multipart * list
Definition: stdsoap2.h:2147
size_t size
Definition: stdsoap2.h:2139
size_t chunksize
Definition: stdsoap2.h:2140
char * ptr
Definition: stdsoap2.h:2143
struct soap_multipart * first
Definition: stdsoap2.h:2148
size_t buflen
Definition: stdsoap2.h:2141
const char * options
Definition: stdsoap2.h:2146
struct soap_multipart * last
Definition: stdsoap2.h:2148
char flags
Definition: stdsoap2.h:2142
const char * id
Definition: stdsoap2.h:2144
const char * type
Definition: stdsoap2.h:2145
size_t count
Definition: stdsoap2.h:2138
struct soap_dom_attribute * next
Definition: stdsoap2.h:2382
const char * name
Definition: stdsoap2.h:2384
struct soap_dom_element * next
Definition: stdsoap2.h:2485
const char * nstr
Definition: stdsoap2.h:2489
struct soap * soap
Definition: stdsoap2.h:2497
const char * code
Definition: stdsoap2.h:2493
const char * lead
Definition: stdsoap2.h:2491
const char * tail
Definition: stdsoap2.h:2494
const void * node
Definition: stdsoap2.h:2495
struct soap_dom_element * elts
Definition: stdsoap2.h:2487
struct soap_dom_element * prnt
Definition: stdsoap2.h:2486
struct soap_dom_attribute * atts
Definition: stdsoap2.h:2488
const char * name
Definition: stdsoap2.h:2490
const char * text
Definition: stdsoap2.h:2492
size_t index
Definition: stdsoap2.h:3007
void * ptr
Definition: stdsoap2.h:3005
struct soap_flist * next
Definition: stdsoap2.h:3003
unsigned int level
Definition: stdsoap2.h:3006
void(* finsert)(struct soap *, int, int, void *, size_t, const void *, void **)
Definition: stdsoap2.h:3008
void * ptr
Definition: stdsoap2.h:3017
char id[1]
Definition: stdsoap2.h:3024
struct soap_ilist * next
Definition: stdsoap2.h:3014
size_t size
Definition: stdsoap2.h:3016
struct soap_flist * flist
Definition: stdsoap2.h:3021
void * smart
Definition: stdsoap2.h:3022
void * link
Definition: stdsoap2.h:3019
void ** spine
Definition: stdsoap2.h:3018
short shaky
Definition: stdsoap2.h:3023
void * copy
Definition: stdsoap2.h:3020
struct soap_multipart * first
Definition: stdsoap2.h:2164
const char * start
Definition: stdsoap2.h:2162
char * boundary
Definition: stdsoap2.h:2161
struct soap_multipart * last
Definition: stdsoap2.h:2164
struct soap_multipart * list
Definition: stdsoap2.h:2163
const char * type
Definition: stdsoap2.h:2197
struct soap_multipart * next
Definition: stdsoap2.h:2193
const char * options
Definition: stdsoap2.h:2198
const char * ptr
Definition: stdsoap2.h:2194
const char * description
Definition: stdsoap2.h:2201
enum soap_mime_encoding encoding
Definition: stdsoap2.h:2199
const char * id
Definition: stdsoap2.h:2196
const char * location
Definition: stdsoap2.h:2200
unsigned int level
Definition: stdsoap2.h:2012
short index
Definition: stdsoap2.h:2013
char id[1]
Definition: stdsoap2.h:2015
struct soap_nlist * next
Definition: stdsoap2.h:2011
const char * ns
Definition: stdsoap2.h:2014
struct soap_plist plist[SOAP_PTRBLK]
Definition: stdsoap2.h:2052
struct soap_pblk * next
Definition: stdsoap2.h:2051
char mark1
Definition: stdsoap2.h:2044
void * dup
Definition: stdsoap2.h:2039
struct soap_plist * next
Definition: stdsoap2.h:2037
char mark2
Definition: stdsoap2.h:2045
const void * ptr
Definition: stdsoap2.h:2038
const void * array
Definition: stdsoap2.h:2040
void(* fdelete)(struct soap *soap, struct soap_plugin *p)
Definition: stdsoap2.h:3033
void * data
Definition: stdsoap2.h:3031
const char * id
Definition: stdsoap2.h:3030
struct soap_plugin * next
Definition: stdsoap2.h:3029
int(* fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src)
Definition: stdsoap2.h:3032
char ** type
Definition: stdsoap2.h:2216
char * id
Definition: stdsoap2.h:2215
struct soap_xlist * next
Definition: stdsoap2.h:2212
char ** options
Definition: stdsoap2.h:2217
unsigned char ** ptr
Definition: stdsoap2.h:2213
int * size
Definition: stdsoap2.h:2214
size_t maxoccurs
Definition: stdsoap2.h:2696
int(* fprepareinitrecv)(struct soap *)
Definition: stdsoap2.h:2766
int(* fresponse)(struct soap *, int, ULONG64)
Definition: stdsoap2.h:2739
int sndbuf
Definition: stdsoap2.h:2691
int proxy_port
Definition: stdsoap2.h:2863
const char * capath
Definition: stdsoap2.h:2954
const char * logfile[SOAP_MAXLOGS]
Definition: stdsoap2.h:2885
short bind_inet6
Definition: stdsoap2.h:2685
size_t buflen
Definition: stdsoap2.h:2806
unsigned short linger_time
Definition: stdsoap2.h:2693
soap_mode omode
Definition: stdsoap2.h:2670
void *(* fdimewriteopen)(struct soap *, const char *, const char *, const char *)
Definition: stdsoap2.h:2775
const char * proxy_http_version
Definition: stdsoap2.h:2861
int errnum
Definition: stdsoap2.h:2878
struct soap_plist * pht[SOAP_PTRHASH]
Definition: stdsoap2.h:2712
SOAP_SOCKET socket
Definition: stdsoap2.h:2788
int connect_retry
Definition: stdsoap2.h:2683
const char * override_host
Definition: stdsoap2.h:2853
short mustUnderstand
Definition: stdsoap2.h:2835
short cdata
Definition: stdsoap2.h:2808
int recvfd
Definition: stdsoap2.h:2800
char tmpbuf[SOAP_TMPLEN]
Definition: stdsoap2.h:2821
int(* ffiltersend)(struct soap *, const char **, size_t *)
Definition: stdsoap2.h:2772
int(* fpreparefinalsend)(struct soap *)
Definition: stdsoap2.h:2769
soap_int32 z_crc
Definition: stdsoap2.h:2968
int max_keep_alive
Definition: stdsoap2.h:2860
void * rsa_params
Definition: stdsoap2.h:2947
int(* fclose)(struct soap *)
Definition: stdsoap2.h:2750
soap_wchar ahead
Definition: stdsoap2.h:2807
int(* fsend)(struct soap *, const char *, size_t)
Definition: stdsoap2.h:2751
int sendfd
Definition: stdsoap2.h:2799
FILE * fdebug[SOAP_MAXLOGS]
Definition: stdsoap2.h:2886
const char * passwd
Definition: stdsoap2.h:2724
unsigned int evlev
Definition: stdsoap2.h:2841
void * bio
Definition: stdsoap2.h:2942
int(* fform)(struct soap *)
Definition: stdsoap2.h:2737
int idnum
Definition: stdsoap2.h:2718
size_t bufidx
Definition: stdsoap2.h:2805
size_t chunksize
Definition: stdsoap2.h:2843
const char * userid
Definition: stdsoap2.h:2723
int(* fpreparerecv)(struct soap *, const char *, size_t)
Definition: stdsoap2.h:2768
ULONG64 recv_maxlength
Definition: stdsoap2.h:2675
struct soap_ilist * iht[SOAP_IDHASH]
Definition: stdsoap2.h:2710
const char * keyfile
Definition: stdsoap2.h:2950
short zlib_in
Definition: stdsoap2.h:2973
const char * cafile
Definition: stdsoap2.h:2953
int(* fdel)(struct soap *)
Definition: stdsoap2.h:2734
struct soap_dime dime
Definition: stdsoap2.h:2881
short version
Definition: stdsoap2.h:2667
short body
Definition: stdsoap2.h:2809
char path[SOAP_TAGLEN]
Definition: stdsoap2.h:2846
short zlib_state
Definition: stdsoap2.h:2972
int(* fprepareinitsend)(struct soap *)
Definition: stdsoap2.h:2765
int keep_alive
Definition: stdsoap2.h:2855
unsigned int ip6[4]
Definition: stdsoap2.h:2851
unsigned int ipv6_multicast_if
Definition: stdsoap2.h:2898
const char * c14ninclude
Definition: stdsoap2.h:2891
ULONG64 count
Definition: stdsoap2.h:2814
int(* fput)(struct soap *)
Definition: stdsoap2.h:2732
int cookie_max
Definition: stdsoap2.h:2896
unsigned int ip
Definition: stdsoap2.h:2850
size_t labidx
Definition: stdsoap2.h:2818
const char * origin
Definition: stdsoap2.h:2867
int(* fpatch)(struct soap *)
Definition: stdsoap2.h:2733
const char * http_version
Definition: stdsoap2.h:2697
int(* fconnect)(struct soap *, const char *, const char *, int)
Definition: stdsoap2.h:2744
soap_mode imode
Definition: stdsoap2.h:2669
char * labbuf
Definition: stdsoap2.h:2816
size_t(* fdimeread)(struct soap *, void *, char *, size_t)
Definition: stdsoap2.h:2778
const char * bearer
Definition: stdsoap2.h:2722
int connect_flags
Definition: stdsoap2.h:2682
char href[SOAP_TAGLEN]
Definition: stdsoap2.h:2824
void * ctx
Definition: stdsoap2.h:2944
struct sockaddr addr
Definition: stdsoap2.h:2906
short other
Definition: stdsoap2.h:2832
SOAP_SOCKET recvsk
Definition: stdsoap2.h:2790
unsigned short ssl_flags
Definition: stdsoap2.h:2949
int alloced
Definition: stdsoap2.h:2842
char msgbuf[SOAP_TMPLEN]
Definition: stdsoap2.h:2820
struct soap_attribute * attributes
Definition: stdsoap2.h:2831
const char * proxy_from
Definition: stdsoap2.h:2866
int(* feltbegout)(struct soap *, const char *, int, const char *)
Definition: stdsoap2.h:2763
struct soap_pblk * pblk
Definition: stdsoap2.h:2713
void * ssl
Definition: stdsoap2.h:2943
int(* fposthdr)(struct soap *, const char *, const char *)
Definition: stdsoap2.h:2738
void * d_stream
Definition: stdsoap2.h:2967
unsigned int z_dict_len
Definition: stdsoap2.h:2971
int(* feltendout)(struct soap *, const char *)
Definition: stdsoap2.h:2764
const char * lang
Definition: stdsoap2.h:2702
soap_mode mode
Definition: stdsoap2.h:2668
int(* fshutdownsocket)(struct soap *, SOAP_SOCKET, int)
Definition: stdsoap2.h:2747
int(* fpreparesend)(struct soap *, const char *, size_t)
Definition: stdsoap2.h:2767
int bind_flags
Definition: stdsoap2.h:2684
const char * encodingStyle
Definition: stdsoap2.h:2700
const char * cors_method
Definition: stdsoap2.h:2870
float z_ratio_in
Definition: stdsoap2.h:2978
const char * crlfile
Definition: stdsoap2.h:2955
int send_timeout
Definition: stdsoap2.h:2677
void * c_locale
Definition: stdsoap2.h:2961
short pidx
Definition: stdsoap2.h:2714
const char * prolog
Definition: stdsoap2.h:2849
int(* fheader)(struct soap *)
Definition: stdsoap2.h:2742
const char * x_frame_options
Definition: stdsoap2.h:2874
int accept_timeout
Definition: stdsoap2.h:2680
void *(* fmimewriteopen)(struct soap *, void *, const char *, const char *, const char *, enum soap_mime_encoding)
Definition: stdsoap2.h:2781
ULONG64 length
Definition: stdsoap2.h:2815
const char * password
Definition: stdsoap2.h:2952
int(* fwvalidate)(struct soap *, const char *, const wchar_t *)
Definition: stdsoap2.h:2760
const char * wsuid
Definition: stdsoap2.h:2889
const char * float_format
Definition: stdsoap2.h:2671
const char * proxy_userid
Definition: stdsoap2.h:2864
int(* fpoll)(struct soap *)
Definition: stdsoap2.h:2753
unsigned int maxlevel
Definition: stdsoap2.h:2694
unsigned int tcp_keep_cnt
Definition: stdsoap2.h:2859
union soap::@28 peer
unsigned int tcp_keep_intvl
Definition: stdsoap2.h:2858
int(* feltendin)(struct soap *, const char *, const char *)
Definition: stdsoap2.h:2762
const char * dime_id_format
Definition: stdsoap2.h:2674
short shaky
Definition: stdsoap2.h:2715
void(* fdimewriteclose)(struct soap *, void *)
Definition: stdsoap2.h:2777
int(* fget)(struct soap *)
Definition: stdsoap2.h:2731
const char * client_addr_ipv6
Definition: stdsoap2.h:2902
void(* fdimereadclose)(struct soap *, void *)
Definition: stdsoap2.h:2776
short root
Definition: stdsoap2.h:2833
size_t lablen
Definition: stdsoap2.h:2817
size_t peerlen
Definition: stdsoap2.h:2910
unsigned int tcp_keep_idle
Definition: stdsoap2.h:2857
short encoding
Definition: stdsoap2.h:2834
const char * authrealm
Definition: stdsoap2.h:2725
const char * z_dict
Definition: stdsoap2.h:2970
void * user
Definition: stdsoap2.h:2719
short bind_v6only
Definition: stdsoap2.h:2686
int override_port
Definition: stdsoap2.h:2854
struct SOAP_ENV__Fault * fault
Definition: stdsoap2.h:2717
int errmode
Definition: stdsoap2.h:2877
int(* fdimewrite)(struct soap *, void *, const char *, size_t)
Definition: stdsoap2.h:2779
struct soap_blist * blist
Definition: stdsoap2.h:2706
const char * cors_allow
Definition: stdsoap2.h:2869
const char * client_addr
Definition: stdsoap2.h:2901
int session_port
Definition: stdsoap2.h:2957
int client_port
Definition: stdsoap2.h:2903
size_t chunkbuflen
Definition: stdsoap2.h:2844
void * session
Definition: stdsoap2.h:2945
const char * is
Definition: stdsoap2.h:2796
int(* fhead)(struct soap *)
Definition: stdsoap2.h:2736
unsigned int level
Definition: stdsoap2.h:2810
struct soap_mlist * mht[SOAP_PTRHASH]
Definition: stdsoap2.h:2887
unsigned short z_level
Definition: stdsoap2.h:2977
char id[SOAP_TAGLEN]
Definition: stdsoap2.h:2823
int recverror
Definition: stdsoap2.h:2771
int(* fclosesocket)(struct soap *, SOAP_SOCKET)
Definition: stdsoap2.h:2746
short part
Definition: stdsoap2.h:2838
long maxlength
Definition: stdsoap2.h:2695
unsigned char ipv4_multicast_ttl
Definition: stdsoap2.h:2900
const char * client_interface
Definition: stdsoap2.h:2904
int(* fopt)(struct soap *)
Definition: stdsoap2.h:2735
int(* fserveloop)(struct soap *)
Definition: stdsoap2.h:2756
int(* fparse)(struct soap *)
Definition: stdsoap2.h:2740
int socket_flags
Definition: stdsoap2.h:2681
struct sockaddr_in in
Definition: stdsoap2.h:2907
char session_host[SOAP_TAGLEN]
Definition: stdsoap2.h:2956
SOAP_SOCKET(* fopen)(struct soap *, const char *, const char *, int)
Definition: stdsoap2.h:2748
void *(* fdimereadopen)(struct soap *, void *, const char *, const char *, const char *)
Definition: stdsoap2.h:2774
void * fsslverify
Definition: stdsoap2.h:2941
struct sockaddr_storage storage
Definition: stdsoap2.h:2908
void * alist
Definition: stdsoap2.h:2708
short state
Definition: stdsoap2.h:2666
SOAP_SOCKET master
Definition: stdsoap2.h:2787
int(* fpost)(struct soap *, const char *, const char *, int, const char *, const char *, ULONG64)
Definition: stdsoap2.h:2730
struct soap_dom_element * dom
Definition: stdsoap2.h:2880
int error
Definition: stdsoap2.h:2876
int(* fresolve)(struct soap *, const char *, struct in_addr *inaddr)
Definition: stdsoap2.h:2743
char host[SOAP_TAGLEN]
Definition: stdsoap2.h:2847
float z_ratio_out
Definition: stdsoap2.h:2979
const char * actor
Definition: stdsoap2.h:2701
ULONG64 start
Definition: stdsoap2.h:2812
void *(* fmimereadopen)(struct soap *, void *, const char *, const char *, const char *)
Definition: stdsoap2.h:2780
struct soap_clist * clist
Definition: stdsoap2.h:2707
struct SOAP_ENV__Header * header
Definition: stdsoap2.h:2716
const char * proxy_host
Definition: stdsoap2.h:2862
void * dh_params
Definition: stdsoap2.h:2946
int(* fdisconnect)(struct soap *)
Definition: stdsoap2.h:2745
int recv_timeout
Definition: stdsoap2.h:2676
char * action
Definition: stdsoap2.h:2848
void(* fmimereadclose)(struct soap *, void *)
Definition: stdsoap2.h:2782
char arrayOffset[SOAP_TAGLEN]
Definition: stdsoap2.h:2828
void * fsslauth
Definition: stdsoap2.h:2940
int(* fmimewrite)(struct soap *, void *, const char *, size_t)
Definition: stdsoap2.h:2785
const char ** os
Definition: stdsoap2.h:2795
size_t(* frecv)(struct soap *, char *, size_t)
Definition: stdsoap2.h:2752
void(* fseterror)(struct soap *, const char **c, const char **s)
Definition: stdsoap2.h:2754
char * ipv4_multicast_if
Definition: stdsoap2.h:2899
char buf[SOAP_BUFLEN]
Definition: stdsoap2.h:2819
int(* fpreparefinalrecv)(struct soap *)
Definition: stdsoap2.h:2770
int port
Definition: stdsoap2.h:2852
struct soap_cookie * cookies
Definition: stdsoap2.h:2893
short event
Definition: stdsoap2.h:2839
const char * keyid
Definition: stdsoap2.h:2951
int(* fsvalidate)(struct soap *, const char *, const char *)
Definition: stdsoap2.h:2759
const char * proxy_passwd
Definition: stdsoap2.h:2865
int accept_flags
Definition: stdsoap2.h:2687
int positions[SOAP_MAXDIMS]
Definition: stdsoap2.h:2830
int(* feltbegin)(struct soap *, const char *)
Definition: stdsoap2.h:2761
const char * long_double_format
Definition: stdsoap2.h:2673
size_t z_buflen
Definition: stdsoap2.h:2976
short null
Definition: stdsoap2.h:2836
int position
Definition: stdsoap2.h:2829
const char * double_format
Definition: stdsoap2.h:2672
struct soap_nlist * nlist
Definition: stdsoap2.h:2705
char type[SOAP_TAGLEN]
Definition: stdsoap2.h:2825
char tag[SOAP_TAGLEN]
Definition: stdsoap2.h:2822
const char * cors_origin
Definition: stdsoap2.h:2868
short peeked
Definition: stdsoap2.h:2840
const char * http_content
Definition: stdsoap2.h:2698
char arraySize[SOAP_TAGLEN]
Definition: stdsoap2.h:2827
char arrayType[SOAP_TAGLEN]
Definition: stdsoap2.h:2826
void(* fmimewriteclose)(struct soap *, void *)
Definition: stdsoap2.h:2783
const char * cors_methods
Definition: stdsoap2.h:2872
size_t(* fmimeread)(struct soap *, void *, char *, size_t)
Definition: stdsoap2.h:2784
int status
Definition: stdsoap2.h:2875
char endpoint[SOAP_TAGLEN]
Definition: stdsoap2.h:2845
SOAP_SOCKET(* faccept)(struct soap *, SOAP_SOCKET, struct sockaddr *, int *n)
Definition: stdsoap2.h:2749
SOAP_SOCKET sendsk
Definition: stdsoap2.h:2789
int(* fignore)(struct soap *, const char *)
Definition: stdsoap2.h:2755
const struct Namespace * namespaces
Definition: stdsoap2.h:2703
int rcvbuf
Definition: stdsoap2.h:2692
const char * ntlm_challenge
Definition: stdsoap2.h:2727
const char * cookie_domain
Definition: stdsoap2.h:2894
struct soap_mime mime
Definition: stdsoap2.h:2882
int connect_timeout
Definition: stdsoap2.h:2679
short zlib_out
Definition: stdsoap2.h:2974
int(* ffilterrecv)(struct soap *, char *, size_t *, size_t)
Definition: stdsoap2.h:2773
char * z_buf
Definition: stdsoap2.h:2975
void * data[4]
Definition: stdsoap2.h:2720
int(* fparsehdr)(struct soap *, const char *, const char *)
Definition: stdsoap2.h:2741
struct Namespace * local_namespaces
Definition: stdsoap2.h:2704
struct soap_xlist * xlist
Definition: stdsoap2.h:2883
int tcp_keep_alive
Definition: stdsoap2.h:2856
const char * cors_headers
Definition: stdsoap2.h:2873
struct soap_plugin * plugins
Definition: stdsoap2.h:2721
short ns
Definition: stdsoap2.h:2837
const char * http_extra_header
Definition: stdsoap2.h:2699
const char * cors_header
Definition: stdsoap2.h:2871
int transfer_timeout
Definition: stdsoap2.h:2678
void *(* fplugin)(struct soap *, const char *)
Definition: stdsoap2.h:2757
const char * c14nexclude
Definition: stdsoap2.h:2890
const char * cookie_path
Definition: stdsoap2.h:2895
#define HANDLE
Definition: violite.h:59
#define const
Definition: zconf.h:214
#define MAX_WBITS
Definition: zconf.h:244
unsigned long uLong
Definition: zconf.h:368
unsigned char Byte
Definition: zconf.h:365
Byte FAR Bytef
Definition: zconf.h:374
#define Z_DEFLATED
Definition: zlib.h:205
#define Z_NEED_DICT
Definition: zlib.h:175
#define Z_BUF_ERROR
Definition: zlib.h:180
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:196
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1634
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1637
#define Z_STREAM_END
Definition: zlib.h:174
#define Z_FINISH
Definition: zlib.h:168
#define Z_OK
Definition: zlib.h:173
struct z_stream_s z_stream
#define Z_NO_FLUSH
Definition: zlib.h:164
#define Z_NULL
Definition: zlib.h:208
#define inflateInit(strm)
Definition: zlib.h:1632
#define deflateInit(strm, level)
Definition: zlib.h:1630